Монодальный трансформатор

Мне нужно использовать моноданный трансформатор списка. Я читал, что существуют проблемы с ListT IO от Control.Monad.List, так как IO не является коммутативным, поэтому я смотрю ListT done right, Но я получаю неожиданное поведение.

Рассмотрим этот простой тест:

test = runListT $ do
  x <- liftList [1..3]
  liftIO $ print x
  y <- liftList [6..8]
  liftIO $ print (x,y)

Использование 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)
[(),(),(),(),(),(),(),(),()]

Использование "ListT done right":

Main> test
1
(1,6)

Это проблема с "ListT done right", или я просто неправильно ее использую? Есть ли предпочтительная альтернатива?

Спасибо!

Ответы

Ответ 1

Это может быть интенсиональным со стороны автора, так как они говорят

он позволяет каждому элементу списка иметь свои собственные побочные эффекты, которые получают только `excecuted ', если этот элемент списка действительно проверен.

Я не уверен, однако. Во всяком случае, вы можете использовать эту функцию для упорядочения целого список:

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

И аналогичный runAll, который возвращает список, должен быть легко построен.

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)