smilingbuddha
smilingbuddha

Reputation: 14660

How to use the ListT monad transformer

I am a newbie to Monad Transformers in Haskell and in particular I am struggling with the ListT monad transformer.

I want to compute a list while doing some IO operations along the way.

Here is an stupid example that does not compile. I want to print x+1 for every member x of a list.

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

This does not compile. I get the error

[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.

I want the code to print 7,8,9. What should I do?

Upvotes: 4

Views: 1672

Answers (1)

Xiaokui Shu
Xiaokui Shu

Reputation: 432

Here's a complete program to answer the question. First, I think what you need (from functionality perspective) is simpler than ListT, or just IO Int. Second, maybe you want to learn ListT, so I also provide the ListT versions. This program also serves as an example to understand toList and traverse_ functions in list-t library. The difference is wonderfully explained in another streaming library: https://github.com/snoyberg/conduit#interleaved-effects

Before compiling, please add mtl and list-t as dependencies in the package.yaml file (assuming you are using stack).

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

Upvotes: 3

Related Questions