次の問題は型演算を使用して解決できると思いますが、まだ解決策が見つかりません。
問題
バイナリ/テキスト ファイル (json、xml など) から解析する文字列から値 (Tries を実装として使用) への有限マップがあります。
type Value = ...
type Attributes = Data.Trie Value
data Object = Object Attributes
各マップには同じ型の値がありますが、キーのセットは同じではありません。特定のキーを必要とする特殊な機能がある場合に常にタイプを切り替える必要がないように、同じキーのセットを持つマップをグループ化します。
data T1
data T2
...
data Object a where
T1 :: Attributes -> Object T1
T2 :: Attributes -> Object T2
...
これにより、次のようなものを書くことができます。
f1 :: Object T1 -> ...
それ以外の
f1 :: Object ->
f1 o | check_if_T1 o = ...
これは機能しますが、2 つの欠点があります。
- Object の同種リストは異種混合になりました。つまり、リスト [Object] はもう持てません。
属性を取得/設定するには、多くのボイラープレートを記述する必要があります。
get :: Object a -> Attributes get (T1 a) = a get (T2 a) = a ...
質問
- ADT のコンストラクターに応じて関数を特殊化するより良い方法はありますか?
リスト [オブジェクト] を持つ能力を取り戻すにはどうすればよいですか? 特定のタイプのみを許可する特別なバージョンの Dynamic はありますか? オブジェクトをもう一度ラップすることを考えましたが、これは多くのボイラープレートを追加します。例えば、
データ TObject = TT1 T1 | TT2 T2 ...
私が必要とするのは:
get :: a -> TObject -> Object a
私が導出できるように:
collect :: a -> [TObject] -> [Object a]
HList を調べましたが、私の問題には合わないと思います。特に、[Object] の型の順序はコンパイル時にわからないためです。
これは機能依存性/型演算を使用して解決できるように思えますが、まだ良い方法を見つけていません。