あなたが失う最大のものは多態的再帰です。岡崎のケータリング可能なリストを考えてみましょう:
data Cat q a = Empty | Cat a (q (Cat q a))
私たちは書くことができます
instance Foldable q => Foldable (Cat q) where
foldMap _ Empty = mempty
foldMap f (Cat a q) = f a <> foldMap (foldMap f) q
しかし、 just を使おうとするとMonoFoldable
行き詰まります。、 に必要なインスタンス制約はq
、forall x . (MonoFoldable (q x), Element (q x) ~ x)
通常の方法では表現できません。でそれを回避することはおそらく可能ですがData.Constraint.Forall
、かなり醜くなります。
より小さな問題は、コードがより複雑な型シグネチャを取得する可能性があることです。例えば、
osum :: (MonoFoldable c, Num (Element c)) => c -> Element c
に劣っているように私を打つ
sum :: (Foldable f, Num n) => f n -> n
修正は簡単です: の定義をMonoFoldable
に変更します
class (a ~ Element c) => MonoFoldable' a c where ...
あなたに与えるだろう
osum' :: (MonoFoldable' n c, Num n) => c -> n
Element
または、完全に破棄して使用する
class MonoFoldable'' a c | c -> a
同様に単純化された署名を提供します。
残念ながら、Michael Snoyman はこの点で私に同意しません。好みの API を公開するために、いつか独自のラッパー パッケージを作成するかもしれません。
更新:QuantifiedConstraints
言語拡張機能が追加されたので、実際に!Foldable
で表現できるようになりました。MonoFoldable