2012-02-09 20 views
6

現在、私はListTモナドトランスを多用しているプロジェクトを書いています。プレーン・リストを使用する場合、非決定性の実装は非常に簡単です。しかし、一度コードをListTに変換しなければならないと、はるかに複雑になりました。。リストとListTモナド・トランスの間をきれいに変換する方法は?

簡単な例として:ListT a[a]からの変換は、実際には2つの機能を構成する必要があります。

conv :: (Monad m) => [a] -> ListT m a 
conv = ListT . return 

それは簡単ですが、私はそれが既に存在しません驚いています。

質問:

  • モナド変換が必要とされる非決定性に対処するためにいくつかのより良い方法はありますか?
  • リスト間できれいに変換するためのテクニック/ライブラリがありますか?ListT

正確な理由は、非常に複雑であるので、私は本当にそれにあまり詳しく説明する必要はありません。

答えて

6

私はこのためのライブラリはないと思います。 convは結局のところ信じられないほど単純な機能ですが、その逆はちょうどrunListTです。

convMaybeTを使用する際に、多くの場合、希望liftMaybe次のようになります

liftMaybe :: (Monad m) => Maybe a -> MaybeT m a 
liftMaybe = MaybeT . return 

私はそれをliftListの線に沿って何かに名前を付けることをお勧めします。

は限り非決定性のためのより良いモナド変換子が行くように、私はsome helpful operationsとの継続ベースのバックトラックロジックモナドであるオレグのLogicT変圧器、に基づいてlogictパッケージ、見てみるお勧めします。ボーナスとして、[]MonadLogicのインスタンスであるため、これらの操作はリストに対しても機能します。


興味深いことに、我々はconvliftMaybeのパターンを一般化機能定義することができます。これはおそらく、あなたのコードはかなり混乱になりますので、私はそれを使用することはお勧めしません

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 

を:)

+0

はい、私は 'conv'は単純な関数であることに同意します。私はちょうどそこにないことにちょうど驚いている。 'ListT'モジュールにはほとんどユーティリティがありません。これは、私がホイールを再構築するように感じさせます。それで全部です。 – julkiewicz

0

私はこれに似たものがあると思っていたので、数ヶ月後にこの質問に出会いました。だから私は、次のを思い付いた:

{-# 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とは何かを持っているように見えます。

しかし、この問題は、実際にはモナド変圧器とそれが基本モナドに与えるモナドとの間に一様なインターフェースがないことです。 MaybeT :: m (Maybe a) -> MaybeT m aListT :: m [a] -> ListT m aがありますが、OTOHはStateT :: (s -> m (a, s)) -> StateT s m aです。これを回避する方法があるかどうかわかりません - それは確かに必要です

関連する問題