Per What are skolems?, this works:
{-# LANGUAGE ExistentialQuantification #-}
data AnyEq = forall a. Eq a => AE a
reflexive :: AnyEq -> Bool
reflexive (AE x) = x == x
But why doesn't this:
reflexive2 :: AnyEq -> Bool
reflexive2 ae = x == x
where
AE x = ae
(or the similar version with let). It produces the errors including:
Couldn't match expected type ‘p’ with actual type ‘a’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor: AE :: forall a. Eq a => a -> AnyEq,
in a pattern binding
at Skolem.hs:74:4-7
Is it possible to make it work by adding some type declaration (a bit like the s :: forall a. I a -> String solution to the withContext example in that question). I feel I want to add an Eq x somewhere.
My (possibly naïve) understanding of how reflexive works is as follows:
- it takes a value of type
AnyEq. This has embedded within it a value of any type provided it is an instance ofEq. This inner type is not apparent in the type signature ofreflexiveand is unknown whenreflexiveis compiled. - The binding
(AE x) = aemakesxa value of that unknown type, but known to be an instance ofEq. (So just like the variables x and y inmyEq :: Eq a => a -> a -> Bool; myEq x y = x == y) - the
==operator is happy based on the implied class constraint.
I can't think why reflexive2 doesn't do the same, except for things like the "monomorphism restriction" or "mono local binds", which sometimes make things weird. I've tried compiling with all combinations of NoMonomorphismRestriction and NoMonoLocalBinds, but to no avail.
Thanks.