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
TypeFamilyto let each type that implements the class specify a context that it needs.The class lets each type specify an additional constraint
Ctx athat the type needs. Thecdictfunction forces the context to follow fromCand provides a way to get at underlyingCtxs without including them in theCtxfor e.g. products.A
CDictis then aDictthat holds both the constraintC aand also whatever additional contextCtx athe typeaneedsThe
Intinstance doesn't need any extra contextThe tuple instance needs both
C aandC bWe can write
fstCDictfor tuples.Incorrect instance
If we try to write an incorrect instance of
Cthat magically summonsShowinstancesIt results in a compiler error