join
効用関数は次のように定義されます。
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
>>=
isMonad m => m a -> (a -> m b) -> m b
とid
isの型を考えると、上記の定義である必要があるように、a -> a
その関数もどのように型付けできますか? この場合はa -> m b
何ですか?m
b
join
効用関数は次のように定義されます。
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
>>=
isMonad m => m a -> (a -> m b) -> m b
とid
isの型を考えると、上記の定義である必要があるように、a -> a
その関数もどのように型付けできますか? この場合はa -> m b
何ですか?m
b
とのa
型のは必ずしも同じ>>=
ではないため、型を次のように言い換えてみましょう。id
a
(>>=) :: Monad m => m a -> (a -> m b) -> m b
id :: c -> c
したがって、 は結局と同じであると結論付けることができますc
。a
少なくとも whenは...id
の 2 番目の引数であり、それは と同じです。と同じです。言い換えると:>>=
c
m b
a
m b
(>>= id) :: Monad m => m (m b) -> m b
dave4420 はそれをヒットしますが、次の発言はまだ役立つと思います。
型を元の型と互換性のある別の型に有効に「書き換える」ために使用できる規則があります。これらの規則には、型変数のすべての発生を他の型に置き換えることが含まれます。
id :: a -> a
、 に置き換えa
てc
取得できますid :: c -> c
。この後者の型は、元の に書き換えることもできますid :: a -> a
。つまり、これら 2 つの型は同等です。原則として、型変数のすべてのインスタンスを元のどこにも出現しない別の型変数に置き換えると、同等の型が得られます。id :: a -> a
、それを に書き換えることができますid :: Int -> Int
。ただし、後者は元に書き直すことができないため、この場合は型を特殊化しています。f :: a -> m b
すべての出現箇所a
をm b
および getに置き換えることができますf :: m b -> m b
。これも元に戻せないので、特化でもあります。最後の例はid
、 の 2 番目の引数としてどのように使用できるかを示しています>>=
。したがって、あなたの質問に対する答えは、次のようにタイプを書き換えて派生させることができるということです。
1. (>>=) :: m a -> (a -> m b) -> m b (premise)
2. id :: a -> a (premise)
3. (>>=) :: m (m b) -> (m b -> m b) -> m b (replace a with m b in #1)
4. id :: m b -> m b (replace a with m b in #2)
.
.
.
n. (>>= id) :: m (m b) -> m b (indirectly from #3 and #4)