I need to use a list monad transformer. I've read that there are potential problems with ListT IO from Control.Monad.List, since IO isn't commutative, so I'm looking at ListT done right. But I'm getting some unexpected behavior.
Consider this simple test:
test = runListT $ do
x <- liftList [1..3]
liftIO $ print x
y <- liftList [6..8]
liftIO $ print (x,y)
Using Control.Monad.List:
Main> test
1
(1,6)
(1,7)
(1,8)
2
(2,6)
(2,7)
(2,8)
3
(3,6)
(3,7)
(3,8)
[(),(),(),(),(),(),(),(),()]
Using "ListT done right":
Main> test
1
(1,6)
Is this a problem with "ListT done right", or am I just using it wrong? Is there a preferred alternative?
Thanks!
All monad transformers are instances of MonadTrans , and so lift is available for them all. There is a variant of lift specific to IO operations, called liftIO , which is the single method of the MonadIO class in Control. Monad. IO.
liftIO allows us to lift an IO action into a transformer stack that is built on top of IO and it works no matter how deeply nested the stack is.
In Haskell a monad is represented as a type constructor (call it m ), a function that builds values of that type ( a -> m a ), and a function that combines values of that type with computations that produce values of that type to produce a new computation for values of that type ( m a -> (a -> m b) -> m b ).
This might be intensional on the part of the author, since they say
it lets each element of the list have its own side effects, which only get `excecuted' if this element of the list is really inspected.
I'm not sure, though. Anyway, you can use this function to sequence the whole list:
runAll_ :: (Monad m) => ListT m a -> m ()
runAll_ (ListT m) = runAll_' m where
runAll_' m = do
mm <- m
case mm of
MNil -> return ()
_ `MCons` mxs -> runAll_' mxs
And an analogous runAll that returns a list should be easy to construct.
main = runAll_ $ do
x <- liftList [1..3]
liftIO $ print x
y <- liftList [6..8]
liftIO $ print (x,y)
1
(1,6)
(1,7)
(1,8)
2
(2,6)
(2,7)
(2,8)
3
(3,6)
(3,7)
(3,8)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With