8

I'm using the -XExistentialQuantification GHC extension to create a heterogeneous container for values of a specific type class (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

Given that all instances of Shape are also instances of Eq, is there a way to make Object an instance of Eq as well?

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

No, because Eq a says you can compare two values of type a. An Eq instance on your object would allow arbitrary pairs of values (of any type that is an instance of Shape) to be compared.

If I have Shape Int and Shape Bool instances, how can I compare Object True with Object 1 for equality?

于 2012-10-22T16:55:47.753 に答える
1

を実装する型Eqの値は、同じ型の別の値とのみ比較できます。実装する他の型の値とは比較できませんEq。したがって、型の異なる 2 つの値がある場合、両方がShape(したがってEq) のインスタンスであっても、それらを比較することはできません。したがって、少なくとも型の Eq インスタンスを使用して、さまざまな型の値を含めることができるため、EqインスタンスをObject持つこともできません。Object

必要なのは、(Shape a, Shape b) => a -> b -> Bool任意の形状を他の形状と比較するために使用できる型の関数です。そのような関数がある場合は、それを使用して のEqインスタンスを作成できますObjectEqただし、型のインスタンスと一致する方法でそのような関数を定義することはできません。

于 2012-10-22T16:55:02.337 に答える