Re: [F#] point-free стиль и IDisposable
От: Пельмешко Россия blog
Дата: 05.10.09 17:07
Оценка: 14 (1)
Здравствуйте, Аноним, Вы писали:

А>В таком виде всё работает. Теперь переписываем extractInfo в point-free стиле:

А>[skipped]
А>и получаем исключение из-за попытки использования закрытого файла. Причина, в принципе, понятна, тем не менее интересно, можно-ли это исправить сохранив point-free стиль extractInfo?

Если чуть чуть преобразовать Ваш код:
let extractInfo' = flip readFile <| flip applyAction
let extractInfo' = (flip readFile) (flip applyAction)
let extractInfo' = (fun act path -> readFile path act) (fun st hd -> applyAction hd st)
let extractInfo' = fun path -> readFile path (fun st hd -> applyAction hd st)

let info' = extractInfo' filePath trim

Я думал, что понимаю, как работает partial application, но эта ситуация вогнала меня в размышления
Решил для себя разобраться как происходит вычисление, всё оказалось очень просто:

1. Вычисляется extractInfo' с аргументом filePath.
2. Вычисляется readFile с аргументом path и (fun st hd -> applyAction hd st) в качестве action.
3. readFile создаёт StreamReader, передаёт его и action в функцию using.
4. using вызывает action, передав 1 аргумент — открытый StreamReader.
5. action запоминает первый аргумент-ридер и возвращает новую функцию, ожидающую ещё один аргумент — handler.
6. using возвращает функцию-результат action'а и закрывает ридер (то есть в функции остаётся ссылка на закрытый StreamReader).
7. Функция возвращается назад и info'передаёт ей handler, но стрим уже закрыт...

Совсем pointfree сделать не вышло, мона вот так:
let extractInfo' path = applyAction >> readFile path

let info' = extractInfo' filePath trim
[F#] point-free стиль и IDisposable
От: Аноним  
Дата: 05.10.09 11:34
Оценка:
Наткнулся на проблему с использованием функции using и point-free стиля. Пусть, например, мы читаем какие-то данные из файла:
#light

open System.IO

let readFile (path : string) action = using (new StreamReader(path)) action

let applyAction handler (stream : System.IO.TextReader) = stream.ReadLine () |> handler

let trim (s : string) = s.Trim ()

let extractInfo path extracter = readFile path <| applyAction extracter

let filePath = @"C:\some_file.txt"

let info = extractInfo filePath  trim // ok


В таком виде всё работает. Теперь переписываем extractInfo в point-free стиле:
let flip f x y = f y x;;

let extractInfo' = flip readFile <| flip applyAction

let info' = extractInfo' filePath trim // System.ObjectDisposedException: Cannot read from a closed TextReader.


и получаем исключение из-за попытки использования закрытого файла. Причина, в принципе, понятна, тем не менее интересно, можно-ли это исправить сохранив point-free стиль extractInfo?
Re[2]: [F#] point-free стиль и IDisposable
От: Пельмешко Россия blog
Дата: 05.10.09 17:20
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Совсем pointfree сделать не вышло...


Уууухухухууу, догнал!!
let extractInfo' = flip (applyAction >> (flip readFile))


Re[3]: [F#] point-free стиль и IDisposable
От: Аноним  
Дата: 07.10.09 08:18
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Здравствуйте, Пельмешко, Вы писали:


П>>Совсем pointfree сделать не вышло...


П>Уууухухухууу, догнал!!

П>
П>let extractInfo' = flip (applyAction >> (flip readFile))
П>


П>


Спасибо большое! Можно, даже, чуть меньше скобок сделать
let extractInfo' = flip (flip readFile << applyAction)


Кстати, в Haskell, похоже, такие ошибки сложнее случайно сделать. Попытка вернуть значение не обёрнутое в IO обламывается ещё на этапе компиляции. Можно, конечно это сделать специально, но тогда сразу становится видно в чём проблема.
Re[4]: [F#] point-free стиль и IDisposable
От: Petrovv  
Дата: 09.10.09 13:54
Оценка:
П>>Уууухухухууу, догнал!!
П>>
П>>let extractInfo' = flip (applyAction >> (flip readFile))
П>>


П>>


А>Спасибо большое! Можно, даже, чуть меньше скобок сделать

А>
А>let extractInfo' = flip (flip readFile << applyAction)
А>


Так тоже работает, скобки не нужны и в примере Пельмешко
let extractInfo' = flip (applyAction >> flip readFile)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.