测试两个异构值之间的相等性

时间:2012-10-22 16:45:59

标签: haskell ghc existential-type

我正在使用-XExistentialQuantification GHC扩展为特定类型类(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的实例?

3 个答案:

答案 0 :(得分: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 

如果所需的cast y类型(使用Just y'y'推断)与实际类型匹配,==将返回x y,否则Nothing

答案 1 :(得分:2)

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

如果我有Shape IntShape Bool个实例,我如何才能将Object TrueObject 1进行比较?

答案 2 :(得分:1)

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

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