" ExistentialQuantification"和Eq实例

时间:2015-03-10 14:24:24

标签: haskell

当我尝试使用ExistentialQuantification时遇到问题

假设你有一个类型

data T s = forall s. (Show s,Eq s) => T (String,s)

我想为这种类型编写一个实例Eq,比如说:

instance Eq (T a) where
    (T (name,value)) == (T (name',value'))  | (name /= name') = False
                                            | otherwise = value == value'

但它失败了:

Could not deduce (s1 ~ s)
from the context (Show s, Eq s)

另一个实例声明

instance Eq a => Eq (T a) where

导致同样的错误:

   Could not deduce (s1 ~ s)
    from the context (Eq a)

2 个答案:

答案 0 :(得分:2)

每次“打开”存在数据类型时,都会显示一个类型已被遗忘的数据。为了解决这个问题,Haskell必须从零开始为这些数据建立一个类型,因此它会生成一个完全唯一的新类型变量。

这意味着如果你打开两个不同的存在,那么无论你做什么,新鲜的类型都不会重合。这是您收到的错误消息的含义。

这当然也是正确的行为。例如,我们需要使用T构造函数的所有内容都是ShowEq的实例。 IntString都满足此要求,因此以下都是有效值

data T = forall s. (Show s,Eq s) => T (String,s)

x, y :: T
x = T ("string", "string")
y = T ("int", 3)

但我们不能指望EqString的{​​{1}}实例足以比较Int作为您的实例3 == "string"尝试做的事情。< / p>

那么如何解决这个问题呢?无论存储在Eq T内的数据类型如何,我们都需要一个平等概念。为此,我们可以建立一个预测,例如

T

其中data T = forall s . T String s (s -> (String, Int)) 的第三个参数是一个函数,它产生值T n表示和一个整数哈希值,我们将用它们进行相等

show

现在这样可行,但是表示会引发一个问题 - 如果我们可以使用我们的匿名类型值执行的 事件将其应用于其同名的匿名函数...那么为什么不呢?首先要做到这一点?

instance Eq T where
  T nm1 s1 f1 = T nm2 s2 f2 = 
    nm1 == nm2 && snd (f1 s1) == snd (f2 s2)

答案 1 :(得分:1)

要扩展我的评论,请按照以下方式进行操作

{-# LANGUAGE ExistentialQuantification #-}
module E where
import Data.Typeable

data T = forall s. (Show s, Eq s, Typeable s) => T String s

instance Eq T where
    T name value == T name' value' = name == name' && maybe False (== value') (cast value)

这假设如果存在主义中的类型不同,则值不应该相等。