我需要使用list monad转换器。我已经从ListT IO
了解Control.Monad.List
存在潜在问题,因为IO
不是可交换的,所以我正在查看ListT done right 。但我得到了一些意想不到的行为。
考虑这个简单的测试:
test = runListT $ do
x <- liftList [1..3]
liftIO $ print x
y <- liftList [6..8]
liftIO $ print (x,y)
使用Control.Monad.List:
Main> test
1
(1,6)
(1,7)
(1,8)
2
(2,6)
(2,7)
(2,8)
3
(3,6)
(3,7)
(3,8)
[(),(),(),(),(),(),(),(),()]
使用&#34; ListT正确完成&#34;:
Main> test
1
(1,6)
这是&#34; ListT做对了&#34;的问题,还是我只是错误使用它?有没有首选替代方案?
谢谢!
答案 0 :(得分:8)
这可能是作者的内涵,因为他们说
但是,我不确定。无论如何,你可以使用这个功能来排序整个 列表:它让列表中的每个元素都有自己的副作用,只有这样才能得到 如果列表的这个元素真的被检查过,那就'已经过了'。
runAll_ :: (Monad m) => ListT m a -> m ()
runAll_ (ListT m) = runAll_' m where
runAll_' m = do
mm <- m
case mm of
MNil -> return ()
_ `MCons` mxs -> runAll_' mxs
返回列表的类似runAll
应该很容易构建。
main = runAll_ $ do
x <- liftList [1..3]
liftIO $ print x
y <- liftList [6..8]
liftIO $ print (x,y)
1
(1,6)
(1,7)
(1,8)
2
(2,6)
(2,7)
(2,8)
3
(3,6)
(3,7)
(3,8)