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 ofreflexive
and is unknown whenreflexive
is compiled. - The binding
(AE x) = ae
makesx
a 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.