我正在尝试创建一个异构的值列表,这些值都属于某个类型类。在我的例子中,typeclass 是一个具有函数依赖关系的多参数 typeclass,但为了简单起见,我将在此处使用 Show typeclass 作为示例(使用 GADT):
data ShowList :: * where
Nil :: ShowList
(:::) :: Show a => a -> ShowList -> ShowList
这很好用,我可以开始将值放入 ShowList
True ::: (3,4) ::: "abc" ::: 3 ::: Nil
我可以毫无问题地编写许多标准列表函数,如映射、过滤、反向、追加等,但是一旦我尝试取出单个元素,
head (x ::: xs) = x
我得到一个错误
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
这个错误是有道理的,因为类型head
必须是Show a => ShowList -> a
,这不是一个合理的类型。
在此示例情况下,存储字符串列表而不是存储Show a
' 列表是可行的,因为唯一可以使用 的实例完成的事情Show
是应用show
并获取字符串。
然而,在我的情况下,我定义的类型类有点复杂:
typeclass Playable a b | a -> b where
play :: a -> Int -> b
所以我不能只存储play x
而不是x
.
有没有办法能够拥有属于类型类的值列表并能够从列表中取出单个值?