我是Haskell的Monad变形金刚的新手,特别是我正在努力使用ListT monad变换器。
我想在沿途进行一些IO操作时计算列表。
这是一个无法编译的愚蠢示例。我想为列表的每个成员x打印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。我该怎么办?
答案 0 :(得分:1)
这是一个完整的程序来回答这个问题。首先,我认为您需要的(从功能角度来看)比ListT
或IO Int
更简单。其次,也许你想学习ListT,所以我也提供了ListT版本。此程序还可以作为一个示例来理解toList
库中的traverse_
和list-t
函数。在另一个流媒体库中可以很好地解释这种差异:https://github.com/snoyberg/conduit#interleaved-effects
在编译之前,请在mtl
文件中添加list-t
和package.yaml
作为依赖项(假设您正在使用堆栈)。
import qualified ListT as L
import Control.Monad.Trans (lift)
main :: IO ()
main = putStrLn "#### Just IO version: maybe you are actually looking for this."
>> scrapJustIO >>= print
>> putStrLn "#### ListT version serializing everything into a list before output."
>> L.toList scrapListT >>= print
>> putStrLn "#### ListT version as stream (what list-t is actually for)"
>> L.traverse_ print scrapListT
scrapJustIO :: IO Int
scrapJustIO = do
putStrLn "Hello"
print 6
mapM_ (print . (+1)) [6,7,8]
return 4
scrapListT :: L.ListT IO Int
scrapListT = do
lift $ putStrLn "Hello"
lift $ print 6
x <- L.fromFoldable [6,7,8]
lift $ print (x+1)
return 4