与GADT特定类型匹配

时间:2017-05-02 02:32:24

标签: haskell gadt data-kinds

使用DataKindsKindSignatures,我可以执行以下操作:

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不是普通类型*,所以T类型T1。其次'T1甚至不属于T类型,它是T2类型的成员,就像T3t等一样,这样就无法区分不同类型。

要尝试解决第一个问题,我可以将Proxy t更改为data DWrap (t :: T) where DWrap :: Proxy t -> D t -> DWrap t

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,这几乎是<input id="uploadBtn" type="file" class="upload" multiple="multiple" name="browsefile" style="display: none !important;"/> <input type="button" value="ファイル追加" onclick="document.getElementById('uploadBtn').click();" style="float: right;"/> <input id="filename" type="hidden" /> <br> <div id="upload_prev"></div> <div style="clear:both;"></div> 的副本。无论如何,我可以避免这个额外的样板并仍然实现我想要做的事情吗?

0 个答案:

没有答案