DataKinds
とを使用するとKindSignatures
、次のことができます。
data T = T1 | T2 | ... | TN
data D (t :: T) where ...
D1 :: ... -> D t
D2 :: ... -> D t
.
.
.
DN :: ... -> D t
しかしもちろん、Haskell は実行時にこの型を削除します。コンストラクターを分離することで、この情報を保持できます。
data D' (t :: T) where ...
D1T1 :: ... -> D' T1
D1T2 :: ... -> D' T2
.
.
.
D1TN :: ... -> D' TN
D2T1 :: ... -> D' T1
D2T2 :: ... -> D' T2
.
.
.
D2TN :: ... -> D' TN
.
.
.
DNT1 :: ... -> D' T1
DNT2 :: ... -> D' T2
.
.
.
DNTN :: ... -> D' TN
そして、パターン マッチを行うと、型もわかります。しかし今、私は必要なコンストラクターの数を吹き飛ばしてしまいました.これはメンテナンスの悪夢になると思います.
私はこのようなことをしたいと思います:
data DWrap (t :: T) where
DWrap :: t -> D t -> DWrap t
DWrap
次に、型を判別するためのパターン マッチを実行できます。
g :: D T1 -> ...
g = ...
f (DWrap T1 x) = g x
と照合すると、 に渡し始めるのに適した型であることがT1
わかるので、これで問題ありません。t
g
もちろん、タイプを無視したい場合は、次のようにします。
h :: D t -> ...
h = ...
f (DWrap _ x) = h x
いずれにせよ、完全性チェックは、私がばかげたことをしていないことを確認する必要があります。
このアプローチを除いては機能しません。まず、t
は kind の通常の型ではないので*
、 kindT
です。第二に、 は typeではなくT1
、type'T1
などのメンバーであるため、型を区別するための無用なアプローチです。T
T2
T3
最初の問題を解決するために、次のように変更できt
ますProxy t
。
data DWrap (t :: T) where
DWrap :: Proxy t -> D t -> DWrap t
これでこの定義はコンパイルされますが、コンストラクターが 1 つしかないdata
ため、型を区別するのにはまったく役に立ちません。Proxy
私はこれを行うことができます:
data TConstructor (t :: T) where
T1Con :: TConstructor T1
T2Con :: TConstructor T2
.
.
.
TNCon :: TConstructor TN
そして、これ:
data DWrap (t :: T) where
DWrap :: TConstructor t -> D t -> DWrap t
そして、次のように一致させることができます:
g :: D T1 -> ...
g = ...
f (DWrap T1Con x) = g x
これでうまくいくはずですが、 を書き出さなければなりません。data TConstructor
これはほとんど のコピーですdata T
。とにかく、この余分なボイラープレートを回避して、私がやろうとしていることを達成することはできますか?