list monad transformer
Asked Answered
I

1

14

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!

Intemperance answered 15/3, 2012 at 18:34 Comment(0)
M
8

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)
Muscadel answered 15/3, 2012 at 19:28 Comment(2)
Hmm, ok this makes sense, and your runAll_ idea is quite nice! I was expecting behavior similar to nested for loops with print statements in an imperative language. But if "ListT done right" is lazy, why is it still performing side effects for the heads of the lists?Intemperance
It's assuming you always want at least the first element, so it wraps the "whole list" in m, and also wraps the cdr in m; the car is not wrapped. If you sequence the "whole list", it exposes just the car.Muscadel

© 2022 - 2024 — McMap. All rights reserved.