カスタムモナドトランスを作成するために(>> =)関数を実装しようとするときにエラーを入力します
-
27-09-2019 - |
質問
将来のプロジェクトのためにMonad Transformerを作成しようとしていますが、残念ながら、Monad Typeclasse(>> =)関数の実装は機能しません。
まず第一に、根底にあるモナドの実装は次のとおりです。
newtype Runtime a = R {
unR :: State EInfo a
} deriving (Monad)
ここで、Monad Typeclasseの実装はGHCによって自動的に行われます( GeneralizedNewtypeDeriving
言語プラグマ)。モナドトランスはそうであると定義されています:
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 >>=
, 、タイプの値を返す必要があります a
. 。この値は、タイプの関数fに渡されます f :: (Monad m) => a -> RuntimeT m b
.
そして、ここにタイプの問題があります: f
関数のタイプは、(>> =)関数で必要なタイプと一致しません。 JOWこのコヒーレントを作ることはできますか?なぜこれがうまくいかないのかわかりますが、それを機能ナルに変えることはできません。
編集:エラーメッセージ:
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.
助けてくれてありがとう、そして私のメッセージの欠陥を修正することをheしないでください、
チャーリーP.
解決
リード・バートンが言ったことから続く StateT
- これがあなたが定義する方法です RuntimeT
使用 StateT
. 。 Runtime
その後、モナドは、IDモナドを使用して些細なことに定義できます。
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)
他のヒント
いつもの StateT s m
モナドは送信します a
に s -> m (a, s)
しかし、あなたは一緒に働いています m (s -> (a, s))
代わりは。後者が将軍のためのモナドを形成するとは思わない s
. 。あなたはただ使いたくないのですか? StateT
?
これが私が考えない理由です a
→ m (s -> (a, s))
モナドです:書くこと >>=
タイプの引数を取る関数が必要です
m (s -> (a, s))
a -> m (s -> (b, s))
タイプの値を返します
m (s -> (b, s))
「エフェクト」(すなわち fmap (const ())
)結果は最初の議論のものでなければなりません。 a
2番目の引数に渡す。以来 m
結果タイプの外側にのみ表示され、2番目の引数をまったく使用することはできません。 m
紹介します。