This is a question concerning constrained polymorphic values, i.e.: values of type forall f. cxt f => a, where cxt is some constraint.
As normal, for such a value to be used, we need some reified constraints type:
data Dict (c :: k -> Constraint) (a :: k) where
Dict :: c a => Dict c a
Now, using such a value directly is simple enough:
runPolymorphicValue :: forall c y b. Dict c y -> (forall a. c a => b) -> b
runPolymorphicValue Dict x = x @y
However, I'm having trouble actually calling this function.
runPolymorphicValueWrapper :: forall c y b. Dict c y -> (forall a. c a => b) -> b
runPolymorphicValueWrapper d x = runPolymorphicValue d x
gives this error message:
error:
• Could not deduce: c a0 arising from a use of ‘x’
from the context: c a
bound by a type expected by the context:
forall (a :: k1). c a => b
Even though x has the desired type forall a. c a => b, it appears that GHC has attempted to monomorphize x immediately upon use, instantiating the c a constraint into c a0 for unknown a0. Obviously, this fails.
In contrast, this definition works fine:
runPolymorphicValue' :: forall c y b. Dict c y -> (forall a. Dict c a -> b) -> b
runPolymorphicValue' Dict f = (f (Dict @c @y))
runPolymorphicValueWrapper' :: forall c y b. Dict c y -> (forall a. Dict c a -> b) -> b
runPolymorphicValueWrapper' d x = runPolymorphicValue' d x
So, how can I actually call a function which takes a parameter of type forall f. cxt f => a?
Broader context:
My end goal is to write a function mapAll which lifts a mapping from types (or some other kind) to values * -> a into a mapping from lists of types to lists of values [*] -> [a], i.e.: mapAll :: (All cxt fs) => (forall f. cxt f => a) -> [a]. Here, All cxt fs means that fs is some list of types, and cxt f holds for each f in fs (see docs). I am able to write this function if I use a forall f. Dict cxt f -> a instead of a forall f. cxt f => a.
Edit
It looks like using forall a. c a => Proxy a -> b instead also works. This should do the job for now, but I'll leave up this question. It sounds like the issue is, indeed, premature monomorphization.
For comparison, I had earlier tried using forall a. c a => () -> b, which gave the same error as the original example.