2012-10-26 19 views
7

モナドの機能を理解するのが難しいです。モナドのインスタンスとしての機能

>>=の実装は少し不可解ようだが、:それについてのミランLipovačasaysは私が混乱して作るでも何

instance Monad ((->) r) where 
    return x = \_ -> x 
    h >>= f = \w -> f (h w) w 

機能(->) rControl.Monad.Instancesで宣言に従ってモナドでありますそれは本当に すべてではありません。 >>=を使用して関数にモナドの値を入力すると、 の結果は常にモナドの値になります。この場合、 関数を別の関数に渡すと、結果も関数になります。それは なので、結果はラムダとして始まります。今までのところ、すべての実装は >>=というように、モナドの値から何らかの形で結果を分離し、その結果に関数fを適用しました。同じ事が起こるのは ここです。関数から結果を得るには、 何かに適用する必要があります。そのため、をここで実行して 関数の結果を取得し、fを適用します。 fはモナドの値を返します。 はこの場合は関数なので、wにも適用します。

(>> =)の型シグネチャはこれです: (>> =)::ミリアンペア - だから私はhは次のように入力されていることを取る>メガバイト

- >( - >メガバイト) m aおよびf(a -> m b)とする。関数がm aの場合は、a型の値を返しますか?またはaタイプの他のものを返すのですか?

hの非モナド値をfに供給されている場合、我々は得る: F(H w)は は正常に見えます。 fは関数であり、その唯一の引数を取っているので、すでに値です、いいえ?モナド関数なので値もモナド値です。なぜそれは別の値wが必要なのですか? wf somethingを非母語にすることはできません。つまり、それはもはや機能ではありません。 f somethinghが同じ引数のwをとり、異なる値のタイプ(m am b)を返す理由も理解できません。

答えて

10

まず、ここで(>>=)のタイプですいくつか余分なカッコ:

(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b 

その時点で、それは何が起こっているのか確認するためにはるかに簡単にする必要があります:タイプaの何かを得るために最初の引数に与えられている(タイプrの)第三引数、結果と三番目の引数の両方のこと第2引数に与えられ、タイプbの最終結果を得る。

したがって、Monadとしての((->) r)は、そのモナドのすべての値に対する追加の関数引数を表し、モナド値が結合されると、単一の "余分な"引数が複製されて各入力値に与えられます。基本的に、これはモナドの値に対して「読み取り専用のグローバル環境」を作成します。この解釈は、Readerモナドとして明示的に提供されています。これは、((->) r)のラッパーです。

+0

ありがとうございます。すべてがクリアです! – amemus

5

それはを見て、このモナドを理解することは、おそらく簡単です何をするかjoin、モナドは同等fmapjoin代わりの>>=を使用して定義することができるからです。

joinの一般形式は、タイプがMonad m => m (m b) -> m bなので、「2層」のモナド値をとり、1つのレイヤーに縮小します。

関数monadの場合、m ~ (a ->)なので、joinの型は(a -> a -> b) -> (a -> b)なので、2つの引数の関数を取り、1つしか取らない関数を返します。

join :: (a -> a -> b) -> (a -> b) 
join f = \x -> f x x 

ご覧のとおり、引数は重複しています。

同様に、関数上のfmapは単に関数の構成であり、returnconstです。

>>=の意味を理解しようとするよりも、この方法を理解する方がはるかに簡単だと思います。 mの専門((->) r)へと今

(>>=) :: (Monad m) => m a -> (a -> m b) -> m b 

、::

(>>=) :: ((->) r) a -> (a -> ((->) r) b) -> ((->) r) b 

すべての機能矢印中置で書き換え:削除

(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b) 

+0

これはインスタンスを概念的に理解するのに便利ですが、 '' = ''の動作を理解して、 ''表記法の各行がそのモナドの意味を把握する必要があります。 –

+0

@ DanBurton:このケースでは、「環境」が常に第1引数であり、Monadインスタンスがパラメータの次数と同等であるため、「Applicative」インスタンスが説明し理解するのが最も簡単だと考えています。 –

関連する問題