I'm playing around with the ConstraintKinds
extension of GHC.
I have the following data type, which is just a box for things fulfilling some one parameter constraint c
:
data Some (c :: * -> Constraint) where
Some :: forall a. c a => a -> Some c
For example, I could construct a box with some kind of number (arguably not very useful).
x :: Some Num
x = Some (1 :: Int)
Now, as long as c
includes the constraint Show
, I could provide an instance of Show (Some c)
.
instance ??? => Show (Some c) where
show (Some x) = show x -- Show dictionary for type of x should be in scope here
But how do I express this requirement in the instance context (marked with ???
)?
I cannot use an equality constraint (c ~ Show
), because the two are not necessarily equal. c
could be Num
, which implies, but is not equal to, Show
.
Edit
I realised that this cannot be possible in general.
If you have two values of type Some Eq
, it is not possible to compare them for equality. They could be of different types that each have their own notion of equality.
What applies to Eq
applies to any type class in which the type parameter appears on the right hand side of the first function arrow (like the second a
in (==) :: a -> a -> Bool
).
Considering that there is no way to create a constraint expressing "this type variable is not used beyond the first arrow", I don't think it is possible to write the instance I want to write.
Num
no longer requires aShow
instance it might be helpful to find a different example. – Cyma??? = Foo c
andFoo
is a custom class to this purpose on the line ofclass Foo c where fooShow :: c a => a -> String
, which needs to be instantiated manually with all the suitablec
s (which I understand it's not your aim). – PatellateClass
class in that package is the closest Edward Kmett was able to get to this. I would guess you'd probably need to change the type checker to go the rest of the way. – Conscription