(...) Typeclassopedia の記事によると、Monad にする前に、特定の型を Applicative にする必要があります (または、理論上はそうする必要があります)。
はい、括弧はさておき、まさにここでの問題です。理論的には、 anyも であるMonad
必要がApplicative
ありますが、歴史的な理由から (つまり、Monad
がより長く使用されているため)、実際には必須ではありません。の特徴はこれだけではありませんMonad
。
base
Hackageのパッケージのソースから取得した、関連する型クラスの実際の定義を検討してください。
ここにありApplicative
ます:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
...次のことが観察できます。
- 現在存在する型クラスを考えると、コンテキストは正しいです。つまり、 が必要
Functor
です。
- これは、タプルを持ち上げるという (おそらく数学的な観点からはより自然な) 用語ではなく、関数の適用に関して定義されています。
- これには、定数関数を持ち上げるのと同等の技術的に余分な演算子が含まれています。
一方、ここにありますMonad
:
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
...次のことが観察できます。
- コンテキストは を無視するだけ
Applicative
でなく、 も無視しますFunctor
。どちらも によって論理的に暗示されていますMonad
が、明示的には必須ではありません。
return
と を使用したより数学的に自然な定義ではなく、関数の適用に関しても定義されますjoin
。
- これには、定数関数を持ち上げるのと同等の技術的に余分な演算子が含まれています。
fail
まったく当てはまらないものも含まれます。
一般に、Monad
型クラスがその基礎となる数学的概念と異なる点は、プログラミングの抽象化としての歴史をさかのぼることができます。いくつかは、それが共有する関数適用バイアスのようApplicative
に、関数型言語に存在することを反映しています。適切なクラスのコンテキストのようなfail
、または欠如などの他のものは、何よりも歴史的な事故です。
つまり、 のインスタンスを持つことは のインスタンスをMonad
意味し、さらに のインスタンスを意味するというApplicative
ことですFunctor
。クラス コンテキストは、これを明示的に形式化するだけです。それは関係なく真実のままです。Monad
現状では、インスタンスが与えられると、完全に一般的な方法で と の両方Functor
をApplicative
定義できます。は、より一般的であるというまったく同じ意味Applicative
よりも「強力ではありません」 。Monad
Monad
Applicative
Applicative
Monad
クラス コンテキストは、Functor f => Applicative f
次の 2 つのことを言います。後者は前者を意味すること、およびその意味を満たすために定義が存在しなければならないことです。多くの場合、後者を定義すると暗黙のうちに前者が定義されますが、コンパイラは一般にそれを推測できないため、両方のインスタンスを明示的に書き出す必要があります。Eq
andで同じことが観察できますOrd
-- 後者は明らかに前者を意味しますが、 のインスタンスを定義するには、Eq
インスタンスを定義する必要がありますOrd
。