Reputation: 29824
Using the following type and class definitions, I do not understand why I get and error when creating the instance
below.
I need MyMap to hold a map of heterogeneous values.
{-# LANGUAGE ExistentialQuantification #-}
module Scratch.SO_ExtistentialTypes where
import Data.Map
type MyMap a = Map String a
class MyClass c where
getMyMap :: forall a. c -> MyMap a
data MyData = forall a. MyData {
myMap :: MyMap a
}
instance MyClass MyData where
getMyMap = myMap -- <= ERROR
Upvotes: 2
Views: 323
Reputation: 77384
For one thing, the forall
here is superfluous:
class MyClass c where
getMyMap :: forall a. c -> MyMap a
Type variables with no explicit binding are universally quantified at the outermost level, so this is exactly the same as just c -> MyMap a
.
Beyond that, a universally quantified type is certainly not going to match an existentially quantified type. The type of getMyMap
says that, given a value of type c
, it will produce a value of type MyMap a
for any possible choice of type a
. On the other hand, the accessor myMap
says that, given a value of type MyData
, it will produce a value of type MyMap a
for some specific but unknown type a
.
It's not possible to have unwrapped existential types floating around by themselves (this would require an exists
quantifier corresponding to forall
), so there's no way to rewrite the type of getMyMap
such that myMap
is a valid implementation.
All you can do with something having an existential type is wrap it back up in another data type that hides the existential quantifier, or give it to a function that has an argument with a universally quantified type. For example, you can use length
on a list [a]
with a
an existential type.
In your case, the values of the Map
have existential type with no other structure or constraints, so they're pretty much useless and might as well be ()
.
Upvotes: 9