8

我正在使用-XExistentialQuantificationGHC 扩展为特定类型类 ( Shape) 的值创建异构容器:

-- Container type
data Object = forall a. Shape a => Object a

-- 'Shape' class. Methods not important
class Eq s => Shape s where
    doStuff :: s -> s

鉴于 的所有实例Shape也是 的实例Eq,有没有办法也创建Object一个实例Eq

4

3 回答 3

19

如果你添加一个Typeable约束是可能的:

import Data.Typeable

data Object = forall a. (Shape a, Typeable a) => Object a

instance Eq Object where
  Object x == Object y =
    case cast y of
      Just y' -> x == y'
      Nothing -> False 

在这里,如果所需的类型(从with的使用推断)与 的实际类型匹配,cast y则返回,否则返回。 Just y'y'==xyNothing

于 2012-10-22T17:20:19.873 回答
2

不,因为Eq a说你可以比较 type 的两个值a。您的对象上的Eq实例将允许比较任意一对值(任何类型的实例Shape)。

如果我有Shape IntShape Bool实例,我该如何比较Object True平等Object 1

于 2012-10-22T16:55:47.753 回答
1

实现的类型的值Eq只能与相同类型的另一个值进行比较——不能与实现的任何其他类型的值进行比较Eq。因此,如果您有两个不同类型的值,即使它们都是Shape(and 因此Eq) 的实例,也无法比较它们。因此,也不可能有一个Eq实例,Object因为它Object可以包含不同类型的值——至少使用类型的 Eq 实例。

您需要的是一个类型函数(Shape a, Shape b) => a -> b -> Bool,可用于将任何形状与任何其他形状进行比较。如果你有这样的功能,你可以用它来EqObject. 但是,您将无法以与类型Eq实例一致的方式定义这样的函数。

于 2012-10-22T16:55:02.337 回答