7

mono-traversableパッケージのMonoFoldableは、通常のすべての Foldable コンテナーなどを実装BytestringできるようMonoFoldableですFoldable。私の質問は、いくつかの高度な GHC 機能を必要とすることを除けMonoFoldableば、 にないもので失われるものはFoldableありますか? これにより、インスタンスの作成者にとって少しトリッキーになり、おそらく見苦しいエラー メッセージが表示されますか?

たとえば、Foldableコンパイルを使用するときにMonoFoldable型が推論されないコードはありますか? または、クライアント (インスタンス ライター コードではない) を大幅に単純化するその他の方法FoldableMonoFoldable?

4

2 に答える 2

4

パラメトリック性が失われます。

タイプ(Foldable f) => f a -> [a]は、 とは大きく異なる保証を提供します(MonoFoldable c) => c -> [Element c]

無料の定理ジェネレーターをいじってプロパティのアイデアを得ることができますが、単純な例として、前者の型は、出力内のすべての要素が入力で発生する必要があるというプロパティを提供します。このプロパティは、後者のタイプによって決して保証されません。

于 2016-09-29T19:48:42.423 に答える
4

あなたが失う最大のものは多態的再帰です。岡崎のケータリング可能なリストを考えてみましょう:

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行き詰まります。、 に必要なインスタンス制約はqforall 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

于 2016-09-29T20:51:41.727 に答える