はい。これを「辞書引きスタイル」といいます。時々私が特にトリッキーなことをしているとき、私は型クラスをスクラップして辞書に変換する必要があります。辞書の受け渡しはより強力ですが1、しばしばとても面倒で、概念的に単純なコードはかなり複雑に見えます。私は、Haskell以外の言語で辞書受け渡しスタイルを使用してタイプクラスをシミュレートします(ただし、通常、これは思ったほど優れたアイデアではないことを学びました)。
もちろん、表現力に違いがある場合は常にトレードオフがあります。特定のAPIがDPSを使用して記述されている場合は、より多くの方法で使用できますが、できない場合はAPIがより多くの情報を取得します。これが実際に現れる1つの方法はですData.Set
。これは、Ord
タイプごとに1 つの辞書しかないという事実に依存しています。Set
店舗は、その要素は、に従ってソートOrd
使用すると、1つの辞書とのセットを構築し、別のものを使用して要素を挿入し、DPSで可能なように、あなたは破ることができれば、とSet
の不変、それがクラッシュします。この一意性の問題は、ファントム存在を使用して軽減できます。辞書をマークするために入力しますが、やはり、APIがかなり煩わしく複雑になります。これは、Typeable
API でもほぼ同じように表示されます。
一意性のビットはあまり出てきません。タイプクラスが優れているのは、コードを作成することです。例えば、
catProcs :: (i -> Maybe String) -> (i -> Maybe String) -> (i -> Maybe String)
catProcs f g = f <> g
これは、入力を受け取り、出力を提供する可能性のある2つの「プロセッサ」を受け取り、それらを連結して平坦化しNothing
、DPSで次のように記述する必要があります。
catProcs f g = (<>) (funcSemi (maybeSemi listSemi)) f g
型のシグネチャで既にスペルアウトしているにもかかわらず、基本的には、使用している型をもう一度スペルアウトする必要があり、コンパイラーがすべてのタイプを認識しているため、冗長でした。Semigroup
型で指定されたものを構築する方法は1つしかないため、コンパイラーがそれを行うことができます。これは、Data.Functor.*
コンビネーターのように、多くのパラメトリックインスタンスの定義を開始し、タイプの構造を使用して計算を開始するときに、「複利」タイプの効果をもたらします。これは、deriving via
基本的にすべてを取得できる場所で大きな効果を発揮するために使用されますあなたのために書かれたあなたのタイプの「標準」代数構造。
また、タイプチェックと推論に情報をフィードバックするMPTCとFundepsについても説明しません。私はそのようなことをDPSに変換しようとしたことがありません-それは多くの型の等価性の証明を通過することを含むと思います-とにかく、私は快適になるよりも私の脳のための多くの仕事になると確信していますと。
-
1 Uは、あなたが使用nless reflection
しかし-彼らは力に同等になった場合にreflection
も、使用に面倒なことができます。