Я думал, что в принципе система типов Haskell запрещает вызывать нечистые функции (т.е. f :: a -> IO b
) из чистых, но сегодня я понял, что вызывая их с помощью return
компилируются просто отлично. Например:
h :: Maybe ()
h = do
return $ putStrLn "???"
return ()
Итак, h
работает в монаде may, но тем не менее это чистая функция. При компиляции и запуске он просто возвращает Just ()
, как и следовало ожидать, без фактического ввода-вывода. Я думаю, что лень haskell объединяет вещи (то есть возвращаемое значение putStrLn
не используется - и не может, поскольку его конструкторы значений скрыты, и я не могу сопоставить его с образцом), но почему это законный код? Есть ли другие причины, по которым это разрешено?
В качестве бонуса попутный вопрос: можно ли вообще запретить выполнение действий одной монады изнутри других? Как?