Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 在模式匹配过程中,是否有方法绑定存在数据类型的suppressed类型变量?_Haskell_Pattern Matching_Gadt_Existential Type - Fatal编程技术网

Haskell 在模式匹配过程中,是否有方法绑定存在数据类型的suppressed类型变量?

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) 现在,某些操作(例如插入)可能会更改树的

使用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)
现在,某些操作(例如插入)可能会更改树的深度,也可能不会更改树的深度。所以我想对类型签名隐藏它。我使用存在数据类型来实现这一点

--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)
的类型。如果值相等,那么类型肯定也相等,并且您可以在以后需要时收集证据。同样有用的是只检查类型相等性的版本。