hPutChar :: Handle -> Char -> IO ()
- это чистая функция Haskell, которая, учитывая два аргумента h :: Handle
и c :: Char
, создает чистое значение Haskell типа IO ()
, "IO
action":
h :: Handle c :: Char
---------------------------------------------
hPutChr h c :: IO ()
Это "действие" является просто значением Haskell, но когда оно появляется внутри блока IO
monad do
в main
, оно становится выполненным системой времени исполнения Haskell и затем фактически выполняет операцию ввода / вывода, помещая символ c
в объект файловой системы, указанный дескриптором h
.
Что касается лямбда-функции, то фактический однозначный синтаксисэто
(\ h -> ... )
, где пробел между \
и h
является необязательным, а все выражение (.......)
является лямбда-выражением.Таким образом, существует no"\h
entity":
(\ ... -> ... )
- синтаксис лямбда-выражения; h
в \ h ->
- это параметр лямбда-функции, ...
в (\ h -> ... )
- это тело лямбда-функции.
bracket
вызывает лямбда-функцию (\h -> hPutChar h c)
с результатом, полученным в результате вычисления (openFile fp WriteMode)
I / O , которое является дескриптором имени файла, на который ссылается fp
, открытого в соответствии с режимом WriteMode
.
Главное, что нужно понять о монадическом вводе-выводе в Haskell, это то, что «вычисление» - это не функция: это фактическое (здесь, ввод / вывод) вычисление, выполняющее фактическое открытие файла - которое создает дескриптор -которая затем используется системой времени выполнения для вызова с ней чистой функции Haskell (\ h -> ...)
.
Этот слой (чистого "мира" Хаскелла и нечистого "мира" ввода / вывода) является сущностью .... да, Монады .Вычисление ввода / вывода что-то делает, находит какое-то значение, использует его для вызова чистой функции Haskell, которая создает новое вычисление, которое затем запускается, передает его результаты в следующую чистую функцию и т. Д. И т. Д. И т. Д.
Так что мы сохраняем нашу чистоту в Хаскеле , только говоря о нечистых вещах.Говорить не надо.
Или это?