3

将来のプロジェクトのためにモナド変換子を作成しようとしていますが、残念ながら、モナド型クラスの (>>=) 関数の実装が機能しません。

まず、基礎となるモナドの実装は次のとおりです。

newtype Runtime a = R { 
  unR :: State EInfo a
} deriving (Monad)

ここで、Monad 型クラスの実装は GHC によって ( GeneralizedNewtypeDerivinglanguage プラグマを使用して) 自動的に行われます。モナド変換子は次のように定義されます。

newtype RuntimeT m a = RuntimeT {
  runRuntimeT :: m (Runtime a)
} 

問題は、Monad typeclasse の (>>=) 関数をインスタンス化する方法に起因します。

instance (Monad m) => Monad (RuntimeT m) where
    return a = RuntimeT $ (return . return) a
    x >>= f =  runRuntimeT x >>= id >>= f

私の見方では、最初は基礎となるモナド>>=で実行されます。mしたがって、runRuntimeT x >>=タイプの値を返しますRuntime a(そうですか?)。次に、次のコードid >>=は type の値を返す必要がありますa。この値は、 type の関数 f に渡されf :: (Monad m) => a -> RuntimeT m bます。

ここで型の問題が発生します。f関数の型が (>>=) 関数で必要な型と一致しません。これを首尾一貫させることができますか?これが機能しない理由はわかりますが、機能的なものに変えることはできません。

編集:エラーメッセージ:

Core.hs:34:4:
    Occurs check: cannot construct the infinite type: m = RuntimeT m
    When generalising the type(s) for `>>='
    In the instance declaration for `Monad (RuntimeT m)'
Failed, modules loaded: none.

助けてくれてありがとう、
チャーリー P.

4

2 に答える 2

4

通常のStateT s mモナドはに送信as -> m (a, s)ますが、m (s -> (a, s))代わりに作業しています。後者が general のモナドを形成するとは思わないs。を使用したくないだけですStateTか?


a→がモナドではないと思う理由はm (s -> (a, s))次のとおりです: To write >>=I need a function that takeargs of types

m (s -> (a, s))
a -> m (s -> (b, s))

タイプの値を返します

m (s -> (b, s))

2 番目の引数に渡す を取得する方法がないため、結果の「効果」(すなわちfmap (const ())) は最初の引数のものでなければなりません。aは結果の型の外側にしか現れないため、2 番目の引数は何にも使用できません。導入されたmを取り除く方法はありません。m

于 2010-04-18T14:43:36.170 に答える
3

リード・バートンが言ったことに続くために-これがあなたがを使ってStateT定義する方法です。モナドは、アイデンティティモナドを使用して簡単に定義できます。RuntimeTStateTRuntime

newtype RuntimeT m a = R { 
  unR :: StateT EInfo m a
}

type Runtime = RuntimeT Identity

instance Monad m => Monad (RuntimeT m) where
    return = R . return

    (R m) >>= f = R (m >>= unR . f)
于 2010-04-18T23:58:38.127 に答える