Почему Haskell нельзя обмануть в выполнении операций ввода-вывода с помощью строгой оценки?
Я только изучаю Хаскель и IO монады. Я задаюсь вопросом, почему это не заставило бы программу выводить "привет" так же как "пока":
second a b = b
main = print ((second $! ((print "hi") >>= (\r -> return ()))) "bye")
Насколько я понимаю, $!
оператор заставит первый аргумент second
подлежит оценке, а >>=
Оператору нужно будет запустить print "hi"
чтобы получить значение от него и передать его \r -> return ()
, который вывел бы "привет" на экран.
Что не так с моими рассуждениями?
А также, есть ли способ доказать, что Haskell нельзя обмануть (кроме использования небезопасных функций) для выполнения операций ввода-вывода внутри "безопасного" кода?
2 ответа
Выражение, которое вы заставляете ((print "hi") >>= (\r -> return ()))
, который имеет тип IO ()
, Как таковой, он представляет действие ввода-вывода. Но оценка такой вещи совершенно отличается от ее запуска!
Оценка значения означает выполнение достаточного количества шагов, чтобы превратить его в так называемую нормальную форму слабой головы. Так как IO
абстрактно, немного сложно понять, что это значит в этом случае, но можно подумать IO a
как RealWorld -> (a, RealWorld)
и затем нормальная форма слабой головы, ну, функция, ожидающая, чтобы получить RealWorld
,
Бег предполагает оценку, но также проходит RealWorld
в качестве аргумента, тем самым вызывая IO
эффект произойдет.
Все это не очень специфично для IO
; Ваше замешательство и концепции в равной степени относятся к a -> b
, Если вы понимаете, что $!
делает, когда второй аргумент является функцией, вы поймете, что происходит, когда это действие ввода-вывода.
Вы путаете оценку с исполнением. Когда вы заставляете выражение как print "hi"
, это ничего не распечатывает. Это просто производит значение (в этом случае значение типа IO()
) представляет действие печати чего-либо. Вы можете думать о ценности print "hi"
как рецепт для печати "привет".