Запись строки ввода-вывода в stdout в Haskell

Как мы печатаем вывод функции, возвращающей строку IO в stdout? Я не могу использовать показ или печать.

Ответ 1

Если вы хотите напечатать результат функции foo :: Int -> IO String (например), вы можете сделать

main = do
    str <- foo 12
    putStrLn str

или, без примечаний,

main = foo 12 >>= putStrLn.

Обозначение do - это синтаксический сахар для второго, в котором используется основной комбинатор (>>=), который имеет тип

(>>=) :: Monad m => m a -> (a -> m b) -> m b

IO является экземпляром класса Monad, поэтому вы можете использовать его здесь.

foo :: Int -> IO String
foo 12 :: IO String

putStrLn :: String -> IO ()

(foo 12) >>= putStrLn :: IO ()

Ответ 2

Как мы печатаем вывод функции, которая возвращает строку IO в stdout?

Хорошо, посмотрим. Здесь функция, которая возвращает строку IO:

dumbFunction :: a -> IO String
dumbFunction x = getLine

dumbFunction является немой функцией (но тем не менее функцией!). Он игнорирует свой вход, а затем возвращает getLine, который имеет тип IO String.

Итак, скажите мне, как вы печатаете getLine :: IO String? Ответ в том, что нет! Это то, что мы называем "действием IO". Обратите внимание, что действие IO не является функцией, потому что оно не принимает ввода. (Тем не менее, операции ввода-вывода могут получать входные данные, а также операции ввода-вывода, такие как чтение stdin, как это делает getLine. Но он не считается "функцией", потому что он не принимает никакого традиционного ввода)

Поэтому вместо того, чтобы распечатывать действие, вы, вероятно, захотите запустить действие, а затем распечатать результат. Это можно сделать, как описал Даниэль Фишер (с <-, который можно рассматривать как оператор "run" ).