当我尝试使用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)
答案 0 :(得分:2)
每次“打开”存在数据类型时,都会显示一个类型已被遗忘的数据。为了解决这个问题,Haskell必须从零开始为这些数据建立一个类型,因此它会生成一个完全唯一的新类型变量。
这意味着如果你打开两个不同的存在,那么无论你做什么,新鲜的类型都不会重合。这是您收到的错误消息的含义。
这当然也是正确的行为。例如,我们需要使用T
构造函数的所有内容都是Show
和Eq
的实例。 Int
和String
都满足此要求,因此以下都是有效值
data T = forall s. (Show s,Eq s) => T (String,s)
x, y :: T
x = T ("string", "string")
y = T ("int", 3)
但我们不能指望Eq
或String
的{{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)
这假设如果存在主义中的类型不同,则值不应该相等。