我正在使用-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
的实例?
答案 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 Int
和Shape Bool
个实例,我如何才能将Object True
与Object 1
进行比较?
答案 2 :(得分:1)
实现Eq
的类型的值只能与同一类型的另一个值进行比较 - 不能与实现Eq
的任何其他类型进行比较。因此,如果您有两个不同类型的值,即使它们都是Shape
(因此Eq
)的实例,也无法比较它们。因此,Eq
的{{1}}实例也是不可能的,因为Object
可以包含不同类型的值 - 至少使用类型'Eq实例。
您需要的是Object
类型的函数,可用于将任何形状与任何其他形状进行比较。如果您有这样的功能,可以使用它为(Shape a, Shape b) => a -> b -> Bool
创建Eq
实例。但是,您将无法以与类型“Object
实例一致的方式定义此类函数。”