2

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わかるので、これで問題ありません。tg

もちろん、タイプを無視したい場合は、次のようにします。

h :: D t -> ...
h = ...

f (DWrap _ x) = h x

いずれにせよ、完全性チェックは、私がばかげたことをしていないことを確認する必要があります。

このアプローチを除いては機能しません。まず、tは kind の通常の型ではないので*、 kindTです。第二に、 は typeではなくT1、type'T1などのメンバーであるため、型を区別するための無用なアプローチです。TT2T3

最初の問題を解決するために、次のように変更でき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。とにかく、この余分なボイラープレートを回避して、私がやろうとしていることを達成することはできますか?

4

0 に答える 0