6

join効用関数は次のように定義されます。

join :: (Monad m) => m (m a) -> m a
join x = x >>= id

>>=isMonad m => m a -> (a -> m b) -> m bidisの型を考えると、上記の定義である必要があるように、a -> aその関数もどのように型付けできますか? この場合はa -> m b何ですか?mb

4

2 に答える 2

14

とのa型のは必ずしも同じ>>=ではないため、型を次のように言い換えてみましょう。ida

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

したがって、 は結局と同じであると結論付けることができますc a少なくとも whenは...idの 2 番目の引数であり、それは と同じです。と同じです。言い換えると:>>=cm bam b

(>>= id) :: Monad m => m (m b) ->               m b
于 2012-04-20T21:05:42.277 に答える
10

dave4420 はそれをヒットしますが、次の発言はまだ役立つと思います。

型を元の型と互換性のある別の型に有効に「書き換える」ために使用できる規則があります。これらの規則には、型変数のすべての発生を他の型に置き換えることが含まれます。

  • がある場合はid :: a -> a、 に置き換えac取得できますid :: c -> c。この後者の型は、元の に書き換えることもできますid :: a -> a。つまり、これら 2 つの型は同等です。原則として、型変数のすべてのインスタンスを元のどこにも出現しない別の型変数に置き換えると、同等の型が得られます。
  • 型変数のすべてのオカレンスを具象型に置き換えることができます。つまり、 があればid :: a -> a、それを に書き換えることができますid :: Int -> Int。ただし、後者は元に書き直すことができないため、この場合は型を特殊化しています。
  • 2 番目のルールよりも一般的には、型変数のすべての出現箇所を任意の型、具象型または変数型に置き換えることができます。たとえば、 がある場合、f :: a -> m bすべての出現箇所am 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)
于 2012-04-21T00:57:22.810 に答える