Haskell 在模式匹配过程中,是否有方法绑定存在数据类型的suppressed类型变量?
使用GADTs,我定义了一个深度索引树数据类型()。该深度用于静态确保树木平衡Haskell 在模式匹配过程中,是否有方法绑定存在数据类型的suppressed类型变量?,haskell,pattern-matching,gadt,existential-type,Haskell,Pattern Matching,Gadt,Existential Type,使用GADTs,我定义了一个深度索引树数据类型()。该深度用于静态确保树木平衡 ——自然数 数据Nat=Z | S Nat --深度索引2-3树 数据DT::Nat->类型->类型,其中 --节点名称模式:N{{子树}{{包含值} N0_0::DT Z a N2_1::DT n a->a->DT n a ->DT(sn)a N3_2::DT n a->a->DT n a->a->DT n a ->DT(sn)a 推导实例Eq a=>Eq(DT n a) 现在,某些操作(例如插入)可能会更改树的
——自然数
数据Nat=Z | S Nat
--深度索引2-3树
数据DT::Nat->类型->类型,其中
--节点名称模式:N{{子树}{{包含值}
N0_0::DT Z a
N2_1::DT n a->a->DT n a
->DT(sn)a
N3_2::DT n a->a->DT n a->a->DT n a
->DT(sn)a
推导实例Eq a=>Eq(DT n a)
现在,某些操作(例如插入)可能会更改树的深度,也可能不会更改树的深度。所以我想对类型签名隐藏它。我使用存在数据类型来实现这一点
--2-3树
数据T::Type->Type where
T:{unT::DT n a}->T a
插入::a->T a->T a
插入x(T dt)=情况dt
N0\u 0->T$N2\u 1 N0\u 0 x N0\u 0
{- ... -}
到目前为止还不错。我的问题是:
我不知道现在如何在t
上定义Eq
实例Eq a=>Eq(ta)其中
(T x)==(T y)=\u什么
显然,我想这样做:
(T {n = nx} x) == (T {n = ny} y)
| nx == ny = x == y
| otherwise = False
我不知道如何/是否可以在模式匹配中绑定类型变量。而且我也不知道一旦我得到它们,如何比较它们。
(我怀疑Data.Type.Equality
就是为了这个,但我还没有看到任何使用它的例子。)
那么,有没有一种方法可以实现
Eq(ta)
实例,或者在这种情况下有没有其他推荐的方法?您可以使用Data.concure.concure来比较树的内容:只要您将深度参数标记为phantom,它应该愿意给您concure::DT n a->DT m a
当然,这并不能真正解决问题:你想知道它们的类型是否相同。好吧,也许有一些关于Typeable的解决方案,但听起来并不是很有趣。在我看来,这似乎不可能,因为你想要两个矛盾的东西
首先,您希望不同深度的树应该是独立的类型,而不是混合的。这意味着每个处理它们的人都必须知道它们是什么类型的
第二,你希望你可以把这样一棵树给别人,而不告诉他们它有多深,让他们任意咀嚼,然后还给你。如果您需要类型知识来操作它们,它们如何做到这一点
存在主义者不会“压制”类型信息:他们会把它扔掉。与所有类型信息一样,它在运行时消失;而且在编译时也使其不可见
我也不确定你的问题仅仅在于
Eq
:你将如何实现像insert
这样的功能?对于N0\u 0
,这很容易,因为已知它有类型DT Z a
,但对于其他情况,我不知道如何构造DT(sn)a
,当您不知道n
是什么时,将t
封装在t中。您应该编写一个与深度无关的相等运算符,它能够比较两棵树,即使它们具有不同的深度n
和m
dtEq :: Eq a => DT n a -> DT m a -> Bool
dtEq N0_0 N0_0 = True
dtEq (N2_1 l1 x1 r1) (N2_1 l2 x2 r2) =
dtEq l1 l2 && x1 == x2 && dtEq r1 r2
dtEq (N3_2 a1 x1 b1 y1 c1) (N3_2 a2 x2 b2 y2 c2) =
dtEq a1 a2 && x1 == x2 && dtEq b1 b2 && y1 == y2 && dtEq c1 c2
dtEq _ _ = False
那么,对于你的存在类型:
instance Eq a => Eq (T a) where
(T x) == (T y) = dtEq x y
即使在最后一行中,深度未知(因为存在),对于dtEq来说也无关紧要,因为它可以接受任何深度
次要补充说明:dtEq
利用多态递归,因为递归调用可以使用与原始调用不同的深度。Haskell允许多态递归,只要提供显式类型签名。(我们需要一个,因为我们使用的是GADT。)谢谢您的回复。处理这些情况的标准方法是什么(例如,在深度索引树上插入insert
;在长度索引列表上过滤filter
)?通常最好使用类似dtEq::Eq a=>dtna->dtma->Maybe(m:~:n)
的类型。如果值相等,那么类型肯定也相等,并且您可以在以后需要时收集证据。同样有用的是只检查类型相等性的版本。