Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the ListT monad transformer

Tags:

haskell

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?

like image 526
smilingbuddha Avatar asked Sep 01 '25 16:09

smilingbuddha


1 Answers

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
like image 183
Xiaokui Shu Avatar answered Sep 06 '25 03:09

Xiaokui Shu