Короче говоря, вам нужно связать вашу функцию со значением IO
вместо попытки применить к значению, заключенному в значение IO
.
-- instead of whnf printElements (randomList 10)
randomList 10 >>= whnf printElements
randomList
не возвращает список значений;он возвращает действие IO
, которое при выполнении может создать список значений.Игнорируя различные ограничения, вызванные реализацией, типом является
randomList :: (...) => t1 -> IO [t] -- not t1 -> [t]
. Таким образом, вы не можете напрямую работать со списком значений, которые может создать действие IO
;вам нужно использовать экземпляр монады для привязки значения к соответствующей функции.whnf printElements
является одной из таких функций;он берет список и возвращает действие IO
.
whnf printElements :: Show a => [a] -> IO ()
Вместо того, чтобы вытягивать список и передавать его в whnf printElements
, мы «проталкиваем» функцию в an *Значение 1027 * с использованием >>=
.Тип этого оператора, специализированный для монады IO
, равен
(>>=) :: IO a -> (a -> IO b) -> IO b
. В этом случае первое значение IO a
- это значение IO [t]
, возвращаемое randomList
.whnf printElements
- это функция a -> IO b
, с которой мы связываемся.Результатом является новое значение IO
, которое принимает первое значение IO
, извлекает упакованное значение, применяет данную функцию и возвращает результат.
Другими словами, сама монада IO
заботится о том, чтобы отделить результат от randomList
и применить к нему свою функцию, а не делать это явно.
(Вы могли заметить, что я сказал, что >>=
связываетзначение для функции и наоборот. Возможно, точнее будет сказать, что >>=
связывает их вместе в одно IO
действие.)