はい、おそらく便利でしょう。実際、わずかに互換性のないバージョンはすべて役に立ちます。これはちょっと問題です。
そのようなクラスが何を意味するのかが明確ではないため、実際に使用するのは困難です。デフォルト値の選択肢が複数あるタイプにヒットすることは避けられず、インスタンスが提供するものがすぐに明確でない場合は、かなりのそもそもクラスを持つことのすべての利点を失います。
いくつかの例:
たとえばMonoid
、ID要素がデフォルトであることが明らかに期待されます。しかし今、あなたは2つ以上の賢明なMonoid
インスタンスを持っている非常に多くのタイプの問題に戻っています。デフォルトはInteger
0または1ですか?の場合Monoid
、標準ライブラリはnewtype
ラッパーを使用しますが、ラッパーは扱いにくく、ラップされた型を操作するのが困難Monoid
です。アクセスmconcat
などができるので問題なく動作しますが、デフォルト値だけでは面白いことはできません。
Functor
「空の」値を持つ-likeタイプの場合、これは明らかなデフォルトを提供します。これは何MonadPlus
をしているのかAlternative
...そしてまた、と重複しています。Monoid
メモリが私に役立つ場合、これらの3つのインスタンスが同一ではないタイプが少なくとも1つあります。複数の選択肢がある場合、どちらを選びますか?Monoid
リストについて考えてみましょう。空のリストをIDとして、任意のリストを追加して、盲目的に追加できます。しかし、あなたのリストについては、アイデンティティとして持ち上げられたモノイドを与えるMonoids
こともできます。多くのファンクターには類似したインスタンスがありますが、常に両方であるとは限りません。したがって、リストにどちらを選択しても、概念的に他のファンクターと矛盾することになります。zipWith mappend
repeat mempty
Monoid
Functor
のようなユニットタイプ()
の場合、デフォルトを選択するのは難しくありません。しかし、列挙についてはどうでしょうか?最初のコンストラクターを選ぶのは理にかなっていますか?時々ですが、常にではありません。クラスを使用する人々はどのように知るのでしょうか?
どうBounded
ですか?上記のいずれにも当てはまらない場合は、を使用できますminBound
。ただし、上記のタイプの一部Bounded
も同様である可能性があるため、デフォルトが最小値でない場合は、問題を混乱させる可能性があります。
基本的に、それが理にかなっているように見えるのに十分な重複があります...しかし実際には、ここでは少なくとも3つの異なる型クラスを念頭に置いており、それらを統合しようとすることはおそらく最初に思われるほど役に立ちません。
物事をもう少しうまく特定し、「デフォルト」値の明確で一貫性のある意味解釈を与えることができれば、型クラスを停止して何を考えなくMonoid
ても簡単に使用できるように、型クラスを再発明したり、別の既存のクラスを作成したりする必要はありません。デフォルト」が選択されます。しかし、私はそれを機能させることに私の希望を得ることができませんでした。
とは言うものの、標準型クラスでカバーされていない明らかに賢明なケースの1つは、のようなシングルトンです()
。ほとんどの場合、これらはそれほど有用ではありません-明らかな理由で!-おそらくそのようなクラスがない理由です。ただし、そのようなクラスが非常に役立つ場所の1つは、型レベルのシェナニガンを含む何かをしているときです。そのような型は、型レベルと用語レベルの両方で単一の値を表すためです。したがって、そのような型のクラスを使用すると、型レベルの値を自由に操作し、それに付随する用語を思いつくので、たとえば、それに基づいて型クラスインスタンスを選択する可能性のある他の関数に渡すことができます。そのため、私は永続的に不完全なタイプハッカリーライブラリにこれらの線に沿ったクラスを持っています。例:
class TermProxy t where
term :: t
-- This makes explicit the lexical pun of () having type ().
instance TermProxy () where
term = ()
instance (TermProxy a, TermProxy b) => TermProxy (a, b) where
term = (term, term)
ただし、そのようなクラスが他のコンテキストで非常に役立つとは思えません。