Monad.Readerは、実際には関数のカプセル化であることがわかりました。
newtype Reader r a = Reader { runReader :: r -> a }
これはモナドのインスタンスになります、
instance Monad (Reader r) where
return a = Reader $ \_ -> a
m >>= k = Reader $ \r -> runReader (k (runReader m r)) r
対照的に、私は(->)もモナドであることを知っていました。
instance Monad ((->) r) where
return = const
f >>= k = \ r -> k (f r) r
定義から、それらが実際にまったく同じように動作することがわかります。
それで、それらはすべての使用法で交換可能ですか?そして、これら2つのモナドを異なることの実際の重要性は何ですか?
それらは同じです。
State
、Writer
およびReader
マークP.ジョーンズのオーバーロードと高階ポリモーフィズムを使用した関数型プログラミングに触発されました。彼Reader
は次のように定義しました。
Reader
モナドは、(タイプで表されるいくつかの囲み環境で保持された値にアクセスするための演算できるようにするために使用されるr
以下の定義では)。> instance Monad (r->) where > result x = \r -> x > x `bind` f = \r -> f (x r) r
通過するコメントとして、これらの2つの関数は、コンビネータ論理の標準
K
およびS
コンビネータにすぎないことに注意してください。
後で、彼は(ほぼ)今日のことを定義しますMonadReader
:
Reader monads
:いくつかの固定環境を参照する計算を記述するためのモナドのクラス:> class Monad m => ReaderMonad m r where > env :: r -> m a -> m a > getenv :: m r > instance ReaderMonad (r->) r where > env e c = \_ -> c e > getenv = id
getenv
は単にask
、であり、env
ですlocal . const
。したがって、この定義には、のすべての重要な部分がすでに含まれていReader
ます。最終的に、ジョーンズはモナド変換子を定義しますReaderT
(BComp
後方構成です)。
まず、2つの異なる形式の構成を定義すると便利です。前方(
FComp
)および後方(BComp
):> data FComp m n a = FC (n (m a)) > data BComp m n a = BC (m (n a))
[Functor、Monad、OutOfインスタンスを省略]
> type ReaderT r = BComp (r ->)
以来StateT
、WriterT
などがその非トランスバリアントを持っていた、持っている唯一の論理的だったReader r
本当に同じです、(->) r
。
どちらの方法が、最近はReader
、Writer
およびState
そのトランスバリアントで定義されている、とあなたは、それぞれの使用Monad*
型クラスを(MonadReader
)。
それで、それらはすべての使用法で交換可能ですか?
はい。
そして、これら2つのモナドを異なることの実際の重要性は何ですか?
なし。ただし、ReaderT
実際にはモナド変換子であるため、作業が簡単になります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加