如何干净地转换列表和ListT monad变换器?
  我目前正在编写一个项目,我大量使用ListT monad变压器。  使用普通列表时,实现非确定性非常容易。  但是,一旦我不得不将我的代码转换为ListT ,它就变得更加复杂1。 
  作为一个简单的例子:从[a]转换到ListT a实际上需要编写两个函数: 
conv :: (Monad m) => [a] -> ListT m a
conv = ListT . return
虽然很简单,但我感到惊讶,它并不在那里。
问题:
ListT之间来回转换? 1确切的原因相当复杂,所以我不想在此详细阐述。
  我不认为有这样的图书馆;  conv是一个令人难以置信的简单函数,毕竟,其他方法只是runListT 。 
  conv类似于liftMaybe使用时通常需要MaybeT : 
liftMaybe :: (Monad m) => Maybe a -> MaybeT m a
liftMaybe = MaybeT . return
  我建议将其命名为liftList .1 
  就非确定性而言,一个更好的monad变换器,我建议看看基于Oleg的LogicT变换器的逻辑程序包,它是一种基于延续的回溯逻辑单元,带有一些有用的操作。  作为奖励,由于[]是MonadLogic一个实例, MonadLogic这些操作也可以在列表中使用。 
  1有趣的是,我们可以定义一个函数来概括conv和liftMaybe的模式liftMaybe : 
import Data.Foldable (Foldable)
import qualified Data.Foldable as F
choose :: (Foldable t, MonadPlus m) => t a -> m a
choose = F.foldr (a b -> return a `mplus` b) mzero
这可能会让你的代码非常混乱,所以我不建议使用它:)
几个月后我刚刚发现了这个问题,因为我想知道类似这样的事情。 所以我想出了以下几点:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.List
-- | Minimal implementation: either joinLift or joinT
class (MonadTrans t, Monad m) => MonadTransJoin t m | m -> t, t -> m where
    joinLift :: (Monad m', Monad (t m')) => m' (m a) -> t m' a
    joinLift = joinT . lift
    joinT :: (Monad m', Monad (t m')) => t m' (m a) -> t m' a
    joinT = (>>= (joinLift . return))
instance MonadTransJoin MaybeT Maybe where
    joinLift = MaybeT
    joinT = (>>= maybe mzero return)
instance MonadTransJoin ListT [] where
    joinLift = ListT
    joinT = (>>= foldr mcons mzero)
        where mcons x xs = return x `mplus` xs
  到目前为止这么好 - 我的ListT / []对的joinT方法看起来好像与ehird的choose 。 
  但是问题在于,monad变换器和monad的基本monad行为之间实际上没有统一的接口。  我们有MaybeT :: m (Maybe a) -> MaybeT ma和ListT :: m [a] -> ListT ma ,但是OTOH我们有StateT :: (s -> m (a, s)) -> StateT sma 。  我不知道是否有办法解决这个问题 - 它肯定需要 
上一篇: How to cleanly convert between lists and ListT monad transformers?
