Одна из самых важных вещей, которые нужно понять о монаде IO
, заключается в том, что выражение m >>= f
не не выполняет действие m
, и при этом не каждый вызывает функцию f
.
Вместо этого он просто создает новое IO
действие, которое включает в себя m
и f
и, когда оно выполнено, наконец выполняет m
, извлекает возвращаемое значение извонит f
с результатом.
Вот и все.Вся ваша программа на Haskell - это не что иное, как DSL для создания одного действия ввода-вывода, которому назначается main
, который для вас выполнит Haskell runtime .
Поэтому, когда вы пишете
-- Rewritten slightly for brevity
myFunction = do
c <- getChar
putStrLn (if (c == 'q')
then "take action 1"
else "take action 2")
это desugared до
myFunction = getChar >>= (\c -> putStrLn (if (c == 'q') then "take action 1" else "take action 2")
, и вы на самом деле говорите: "Создайте IO
действие, содержащее getChar
и функцию типа Char -> IO ()
, такую, что когдаэто действие выполняется, оно выполняет getChar
и передает результирующее Char
в функцию для создания другого IO
действия, которое должно быть выполнено немедленно. "