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
For one thing, the
forallhere is superfluous: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
getMyMapsays that, given a value of typec, it will produce a value of typeMyMap afor any possible choice of typea. On the other hand, the accessormyMapsays that, given a value of typeMyData, it will produce a value of typeMyMap afor some specific but unknown typea.It’s not possible to have unwrapped existential types floating around by themselves (this would require an
existsquantifier corresponding toforall), so there’s no way to rewrite the type ofgetMyMapsuch thatmyMapis 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
lengthon a list[a]withaan existential type.In your case, the values of the
Maphave existential type with no other structure or constraints, so they’re pretty much useless and might as well be().