Reputation: 14660
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
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