这应该是非常简单的,但我似乎无法解决它。
假设我有自己的List类,在其界面中声明head
和tail
。 List
应该是您所期望的,即同类项目的集合。
然后,我想创建一个实现data
接口的List
类型。
以下代码是我提出的,但它不起作用:你将如何解决它?
class List l where
head :: l -> a -- ERROR! How do I tell: given a list, return an element?
tail :: l -> l
data ConsList a = Nil | Cons a (ConsList a)
instance List (ConsList Int) where
head Nil = error "Empty List"
head (Cons h _) = h
tail Nil = error "Empty List"
tail (Cons _ t) = t
提前致谢!
答案 0 :(得分:12)
不是将List
定义为类型类,而是将其定义为构造函数类:
class List l where
head :: l a -> a
tail :: l a -> l a
data ConsList a = Nil | Cons a (ConsList a)
instance List ConsList where
head Nil = error "Empty List"
head (Cons h _) = h
tail Nil = error "Empty List"
tail (Cons _ t) = t
或者,修复元素类型(注意:对于您的类型ConsList
,这需要灵活的实例):
{-# LANGUAGE FlexibleInstances #-}
class List l where
head :: l -> Int
tail :: l -> l
data ConsList a = Nil | Cons a (ConsList a)
instance List (ConsList Int) where
head Nil = error "Empty List"
head (Cons h _) = h
tail Nil = error "Empty List"
tail (Cons _ t) = t
最后,对于类型系列,你可以做更多花哨的东西,但它真的取决于你的具体情况,如果你应该去那么远(可能不是):
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
class List l where
type Elt l
head :: l -> Elt l
tail :: l -> l
data ConsList a = Nil | Cons a (ConsList a)
instance List (ConsList Int) where
type Elt (ConsList Int) = Int
head Nil = error "Empty List"
head (Cons h _) = h
tail Nil = error "Empty List"
tail (Cons _ t) = t
答案 1 :(得分:7)
你可以
使它成为构造函数类,
class List l where
head :: l a -> a
tail :: l a -> l a
使其成为具有功能依赖性的多参数类型
class List l a | l -> a where
head :: l -> a
tail :: l -> l
使用类型系列
class List l where
type Elem l
head :: l -> Elem l
tail :: l -> l
我认为构造函数类是最好的方法。
答案 2 :(得分:3)
对列表进行抽象的最简单方法是抽象类型构造函数,即超过[]
,而不是[a]
(这是{的语法糖) {1}})。
所以你的班级变成了:
[] a
然后您的实例会相应更改:
class List l where
head :: l a -> a -- now l is applied to the element type
tail :: l a -> l a