如何使用ListT monad转换器

时间:2016-12-14 00:58:29

标签: haskell

我是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。我该怎么办?

1 个答案:

答案 0 :(得分:1)

这是一个完整的程序来回答这个问题。首先,我认为您需要的(从功能角度来看)比ListTIO Int更简单。其次,也许你想学习ListT,所以我也提供了ListT版本。此程序还可以作为一个示例来理解toList库中的traverse_list-t函数。在另一个流媒体库中可以很好地解释这种差异:https://github.com/snoyberg/conduit#interleaved-effects

在编译之前,请在mtl文件中添加list-tpackage.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