2012-06-22 10 views
18

GHCには、DeriveFunctor,DeriveDataTypeableなどのようないくつかの言語フラグがあり、Haskell 98で許可されている以外の型クラスの派生インスタンスのコンパイラ生成を可能にします。これは、Functorのようなものに対して特に意味があります。明らかに自然な派生インスタンスを指示します。なぜGHCはMonoidのインスタンスを派生できないのですか?

なぜ、Monoidはありませんか?これは、単一のデータコンストラクタを持つ任意のデータ型のように思える:

data T = MkT a b c ... 

は、一つは機械的(擬似コードを言い訳)Monoidインスタンスを生成できます。

instance (Monoid a, Monoid b, Monoid c, ...) => Monoid T where 
    mempty = 
    MkT mempty mempty mempty ... 
    mappend (MkT a1 b1 c1 ...) (MkT a2 b2 c2 ...) = 
    MkT (mappend a1 a2) (mappend b1 b2) (mappend c1 c2) ... 

私はderiveパッケージprovides thisことを認識してよ、私の質問は、GHCがなぜそうでないのかということです。

+0

@sdcvvc:これは質問に対する有効な回答のようです。おそらくあなたはそれをそのように掲示するべきですか? –

+0

OK、私は答えました。 – sdcvvc

+1

通常、「Functor」インスタンスを作成するための賢明な方法があります。 「モノイド」についても同じことが当てはまりません。 – augustss

答えて

14

Monoidを導き出すことができないというのは実際のところ決まっていますが、モノイドも非常に一般的なので、通常はタイプをモノイドにする方法はたくさんあります。ここでの例は次のとおり

data T = A | B | C deriving (Eq, Ord, Enum) 

type Mon a = (a, a -> a -> a) 

m1, m2, m3, m4 :: Mon T 
m1 = (A, max) 
m2 = (C, min) 
m3 = (A, \ x y -> toEnum $ (fromEnum x + fromEnum y) `rem` 3) 
m4 = (B, f4) 
f4 A _ = A 
f4 B x = x 
f4 C _ = C 

これは(Monユニット及びバイナリ動作を含有する)Tモノイドを作る4つの合理的な方法を示しています。最初のものは最大を取るモノイドであり、2番目のものは最小値を取るものであり、3番目のものはモジュロ3の算術からのものであり、4番目のものはOrderingタイプのものである。自然な方法としては何も目立っていません。

7

Numと他のいくつかのクラスについて同じ質問をすることができます。これは重要ではありません。複数のコンストラクタを持つデータ型では、他のすべての標準派生が機能します。

代わりに、newtype derived newtype T = MkT (a,b,c) deriving Monoidを使用できます。

同様の拡張:空のデータ型をほぼすべての型クラスのインスタンスにすることができます。

deriving節は、定義済みのクラスに対してのみ機能するため、常にアドホックかつ不都合でした。アドホック拡張をさらに追加すると、言語が複雑になります。代わりに、GHCは最近generic derivingのサポートを受けています。

+1

まあ、「導出」のようなアドホックなので、彼らはその力を拡大し続けました。再び、私は、「モノイド」を得るための代替メカニズムがあることを知っています。代わりに 'DeriveFunctor'(と他のもの)がなぜ存在するのか、' DeriveMonoid'(と他の人)はなぜそうではないのか、具体的に質問しています。それはただのことですか? – mergeconflict

+2

最終的には任意ですが、提案された拡張機能はあまり役に立たないようです。ほとんどのファンクターに対応するための特別な言語機能が私にとっては良いようです。製品のモノイドを扱う特別な言語機能は、追加を保証するものではないようです。スコープについて考える必要があります(もし「モノイド」なら他のクラスは何ですか?)。とにかく便利なモノイドはしばしばnewtypeラッパーを使用することに注意してください。したがって、使用するには醜い(ネストされたコンストラクタに一致する必要がある)その導出形式を使用するために、 'data T = T(Sum Integer)(Endo Char) 'を記述します。 – sdcvvc

+2

sum型の有用なモノイドがたくさんありますが、この実装ではインスタンスを派生できません。=( –

関連する問題