用户定义的List实例

时间:2012-07-10 14:23:53

标签: class haskell types

这应该是非常简单的,但我似乎无法解决它。

假设我有自己的List类,在其界面中声明headtailList应该是您所期望的,即同类项目的集合。 然后,我想创建一个实现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                       

提前致谢!

3 个答案:

答案 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