我是一个Haskell中的Monad Transformers新手,尤其是在ListT Monad Transformer方面我很困惑。
我希望在进行一些IO操作的同时计算一个列表。
这里有一个愚蠢的例子,它无法编译。我想打印列表中每个成员x加1的结果。
import Control.Monad
import Control.Monad.Trans.List
import Control.Monad.Trans.Class
import System.IO.Unsafe
scrap :: ListT IO Int
scrap = do lift $ print "Hello"
lift $ print 6
x <- [6,7,8]
lift $ print (x+1) -- code crashes here
return 4
这段代码不能被编译,会出现以下错误:
[1 of 1] Compiling Main ( problem.hs, interpreted )
problem.hs:41:17:
Couldn't match expected type ‘ListT IO Integer’
with actual type ‘[Integer]’
In a stmt of a 'do' block: x <- [6, 7, 8]
In the expression:
do { lift $ print "Hello";
lift $ print 6;
x <- [6, 7, ....];
lift $ print (x + 1);
.... }
In an equation for ‘scrap’:
scrap
= do { lift $ print "Hello";
lift $ print 6;
x <- [6, ....];
.... }
Failed, modules loaded: none.
我想要代码打印出7,8,9,我应该怎么做?
ListT
修饰子将回溯功能添加到给定的单子中,该单子必须是可交换的。”IO
不是可交换的(这意味着你执行效果的顺序并不重要,在IO
中则很不正确)。这就意味着你不能得到单子定律 - 例如,如果你写do { do { foo; bar }; baz }
它的行为可能与你写do { foo; do { bar; baz } }
不同。而且谁知道它们的差异应该是什么? - 基本上就没有意义了。 - luqui[6,7,8]
的类型是[Int]
,但编译器期望的是ListT IO Int
。因此,你需要进行转换[Int]-> ListT IO Int
。例如,ListT . return $ [6,7,8]
。 - freestylelist-transformer
有一些不错的教程材料。(使用该库,freestyle更正的有问题的行将被写成select [6,7,8]
)Hackage上有几种不同的实现,例如list-t
。 - Michael