Chad Scherrer
Chad Scherrer

Reputation: 773

list monad transformer

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!

Upvotes: 14

Views: 1594

Answers (1)

Owen
Owen

Reputation: 39366

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)

Upvotes: 8

Related Questions