Frage

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?

War es hilfreich?

Lösung

It's possible if you add a Typeable constraint:

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 

Here, cast y will return Just y' if the desired type of y' (inferred from the use of == with x) matches the actual type of y, and Nothing otherwise.

Andere Tipps

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?

A value of a type which implements Eq can only be compared with another value of the same type - not of any other type that implements Eq. So if you have two values of different types, you can't compare them even if they're both instances of Shape (and thus Eq). Therefore it's also impossible to have an Eq instance for Object as an Object can contain values of different types - at least using the types' Eq instances.

What you'd need would be a function of type (Shape a, Shape b) => a -> b -> Bool that can be used to compare any shape to any other shape. If you have such a function, you can use that to create an Eq instance for Object. However you won't be able to define such a function in a way that's consistent with the types' Eq instances.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top