I have a class C
with instances for one type and for tuples.
class C a
instance C Int
instance (C a, C b) => C (a, b)
Using the normal Dict
GADT for capturing constraints
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ConstraintKinds #-}
data Dict c where
Dict :: c => Dict c
is it possible to prove C a
from C (a, b)
?
fstDict :: Dict (C (a, b)) -> Dict (C a)
fstDict Dict = ???
I suspect the immediate answer is "no" since fstDict Dict = Dict
isn't sufficient, and there are few other possibilities. Is there any way to change C
so that constraints for components of products can be recovered from the constraint on the product?
I am, perhaps incorrectly, trying to accomplish the same thing as the most closely related question, however I have the luxury to demand a Dict
from one or both ends of the category.
data DSL a b where
DSL :: (Dict C a -> DSL' a b) -> DSL a b
data DSL' a b where
DSL' :: (C a, C b) => ... -> DSL' a b
An open variant of Daniel Wagner's answer would use a
TypeFamily
to let each type that implements the class specify a context that it needs.The class lets each type specify an additional constraint
Ctx a
that the type needs. Thecdict
function forces the context to follow fromC
and provides a way to get at underlyingCtx
s without including them in theCtx
for e.g. products.A
CDict
is then aDict
that holds both the constraintC a
and also whatever additional contextCtx a
the typea
needsThe
Int
instance doesn't need any extra contextThe tuple instance needs both
C a
andC b
We can write
fstCDict
for tuples.Incorrect instance
If we try to write an incorrect instance of
C
that magically summonsShow
instancesIt results in a compiler error