Почему 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" как рецепт для печати "привет".

Другие вопросы по тегам