In general, I'm wondering if there's a way to write a generic fold that generalizes a function that applies a forall
type like:
f :: forall a. Data (D a) => D a -> b
given some datatype D
for which instance Data (D a)
(possibly with constraints on a
). To be concrete, consider something even as simple as False `mkQ` isJust
, or generally, a query on the constructor of a higher-kinded datatype. Similarly, consider a transformation mkT (const Nothing)
that only affects one particular higher-kinded type.
Without explicit type signatures, they fail with No instance for Typeable a0
, which is probably the monomorphism restriction at work. Fair enough. However, if we add explicit type signatures:
t :: GenericT
t = mkT (const Nothing :: forall a. Data a => Maybe a -> Maybe a)
q :: GenericQ Bool
q = False `mkQ` (isJust :: forall a. Data a => Maybe a -> Bool)
instead we are told that the forall
type of the outer signatures are ambiguous:
Could not deduce (Typeable a0)
arising from a use of ‘mkT’
from the context: Data a
bound by the type signature for:
t :: GenericT
The type variable ‘a0’ is ambiguous
I can't wrap my head around this. If I'm really understanding correctly that a0
is the variable in t :: forall a0. Data a0 => a0 -> a0
, how is it any more ambiguous than in say mkT not
? If anything, I would've expected mkT
to complain because it is the one that interacts with isJust
. Additionally, these functions are more polymorphic than the branching on concrete types.
I'm curious to know if this is a limitation of proving the inner constraint isJust :: Data a => ...
— my understanding is that any type of instance Data
inhabited with Maybe a
must also have Data a
to be valid by the instance constraint instance Data a => Data (Maybe a)
.