了解ListT IO示例

时间:2017-04-11 12:57:44

标签: haskell

从精心编写的From Simple IO to Monad Transformers

中得到以下内容
import Control.Monad.List

type Lio = ListT IO

test :: Lio ()
test = do
   x <- return [1,2]
   y <- ListT $ return ['a', 'b']
   lift $ putStrLn (show (x, y))

请解释输出的最后一行[(), ()]

*Main> runListT test
([1,2],'a')
([1,2],'b')
[(),()]

1 个答案:

答案 0 :(得分:2)

TL; DR:如果您在GHCi中看到了一些您没想到的东西,请考虑产生该结果的行的类型。

test的类型为ListT IO ()。如果我们在runListT上使用ListT m a,我们最终会得到m [a]

runListT      :: Monad m => ListT  m  a  ->  m  [a]
test          ::            ListT IO ()
runListT test ::                            IO [()]

由于可以显示[()](并且不是()),GHCi会显示结果。如果绑定它,你将看不到它:

*Main> res <- runListT test
([1,2],'a')
([1,2],'b')
*Main> res
[(),()]

最后,它与replicateM 10 $ print 1的输出有些相关。它收集print 1的所有结果,这些结果不是很有趣。但是,编写runListT_以删除它们很容易:

*Main> let runListT_ m = runListT m >> return ()
*Main> runListT_ test
([1,2],'a')
([1,2],'b')