Что означают действия ввода-вывода внутри чистых функций?

Я думал, что в принципе система типов Haskell запрещает вызывать нечистые функции (т.е. f :: a -> IO b) из чистых, но сегодня я понял, что вызывая их с помощью returnкомпилируются просто отлично. Например:

h :: Maybe ()
h = do
    return $ putStrLn "???"
    return ()

Итак, hработает в монаде may, но тем не менее это чистая функция. При компиляции и запуске он просто возвращает Just (), как и следовало ожидать, без фактического ввода-вывода. Я думаю, что лень haskell объединяет вещи (то есть возвращаемое значение putStrLnне используется - и не может, поскольку его конструкторы значений скрыты, и я не могу сопоставить его с образцом), но почему это законный код? Есть ли другие причины, по которым это разрешено?

В качестве бонуса попутный вопрос: можно ли вообще запретить выполнение действий одной монады изнутри других? Как?

10
задан Riccardo T. 22 March 2012 в 09:35
поделиться