2012-09-20 8 views
13

source for Monadを見る:typeclassの定義に追加の関数/コンビネータを追加する賛否両論は何ですか?

class Monad m where 
    (>>=)  :: forall a b. m a -> (a -> m b) -> m b 
    (>>)  :: forall a b. m a -> m b -> m b 

    return  :: a -> m a 
    fail  :: String -> m a 

    {-# INLINE (>>) #-} 
    m >> k  = m >>= \_ -> k -- <-- !! right here !! 
    fail s  = error s 

あなたは>>は、デフォルトの実装を持っていることがわかります。私の質問は、それが良いか悪い練習と考えられているのですか?また、なぜ関数型/結合子を型クラスの外に別に提供するのではなく、型クラスをに含めるのですか?

、なぜされていない

class Monad m where 
    (>>=)  :: forall a b. m a -> (a -> m b) -> m b 

    return  :: a -> m a 
    fail  :: String -> m a 

    fail s  = error s 

とどこか別の場所:

(>>)  :: forall a b. m a -> m b -> m b 
{-# INLINE (>>) #-} 
m >> k  = m >>= \_ -> k 

答えて

13

私の知る限りでは、「余分」の機能を含むように2つの主な理由があります。

  • 効率:ときどき非効率的な一般的な実装が存在し、クラスの作者は、インスタンス固有の実装に期待するが、はるかに良い。このような場合、デフォルトの実装を持つクラスの関数を含めることは、必要であればインスタンスが最適化されたバージョンを使用できることを意味しますが、必須ではありません。これの楽しい例については、Foldableをご覧ください。 Monadについても同様です。

  • 実行の選択:多くの場合、使用できるクラス関数のサブセットがいくつかあります。すべての潜在的な機能を含み、デフォルトの実装を相互に使用することは、インスタンスが実装して残りを自動的に取得するいくつかの関数を選択できることを意味します。これはFoldableにも当てはまりますが、より簡単な例はEqです。彼らは一定の法則を満足させなければならないとき、または、彼らは明確にこれらの法律の声明を出すとき

+1

versa.'それは*あなたも*短所をリストでした(!とMonadFunctorのサブクラスを作る)型クラスにすべての4つの演算子を置くためにあなたを奨励し、joinの面で>>=のデフォルトの定義を与え、副? –

+0

@TikhonJelvis:正直言って、そこにはどのような客観的な欠点があるのか​​は分かりません。間違いなくクラスの性質を難読化し、GHCが内部で使用するクラス辞書を膨らませるかもしれませんが、明白で明らかな欠点がある場合、私はそれらを認識しません。 –

+0

それは私が思ったものです。しかし、私が知る限り、これらのデフォルトの実装はかなり頻繁に使用されているので、興味があります。 –

3

この方法では、カスタム>>は、それがより効率的か自然に行うことができますモナドのために実装することができますm >>= \_ -> k経由よりも優先されますが、デフォルト実装はまだ存在します。

3

型クラスのメソッドを含むためのもう一つの引数があります。私は、法律が型どおりに関連していなければならないと主張します(「このクラスのインスタンスを宣言するためには、私は何を提供する必要がありますか?」)。例えば、モナドの法律をreturn,joinreturnおよび>>=ではなくfmapであり、

関連する問題