список монад трансформатор - PullRequest
14 голосов
/ 15 марта 2012

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

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

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 сделано правильно":

Main> test
1
(1,6)

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

Спасибо!

1 Ответ

8 голосов
/ 15 марта 2012

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

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

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

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)
...