I'm trying to create a heterogenous list of values that all belong to a certain typeclass. In my case, the typeclass is a multi-parameter typeclass with functional dependencies, but for simplicity's sake, I'll use the Show typeclass here as an example (using GADTs):
data ShowList :: * where
Nil :: ShowList
(:::) :: Show a => a -> ShowList -> ShowList
This works fine, and I can start putting values in the ShowList
True ::: (3,4) ::: "abc" ::: 3 ::: Nil
I can write many of the standard list functions like, map, filter, reverse, append, etc. with no problem, but as soon as I try to take out a single element,
head (x ::: xs) = x
I get an errror
Could not deduce (t ~ a)
from the context (Show a)
bound by a pattern with constructor
::: :: forall a. Show a => a -> ShowList -> ShowList,
in an equation for `head'
at <interactive>:34:12-19
`t' is a rigid type variable bound by
the inferred type of head :: ShowList -> t at <interactive>:34:5
`a' is a rigid type variable bound by
a pattern with constructor
::: :: forall a. Show a => a -> ShowList -> ShowList,
in an equation for `head'
at <interactive>:34:12
In the expression: x
In an equation for `head': head (x ::: xs) = x
This error makes sense because the type of head
would have to be Show a => ShowList -> a
, which isn't a reasonable type.
In this example situation, it would be feasible, instead of storing a list of Show a
's, to store a list of Strings, since the only thing that can be done with an instance of Show
is apply show
and get a String.
In my situation, however, the typeclass I've defined is a little more complex:
typeclass Playable a b | a -> b where
play :: a -> Int -> b
and so I can't just store play x
instead of x
.
Is there any way be able to have a list of values belonging to a typeclass and be able to take out a single value from the list?