不同种类的类型约束

时间:2011-10-19 04:43:53

标签: haskell typeclass type-constraints

我一直在摆弄Haskell中列表的通用类型。

class HasEmpty a where
  empty :: a
  isEmpty :: a -> Bool

class HasEmpty (l a) => List l where
  cons :: a -> l a -> l a
  uncons :: l a -> (a, l a)

为了让您了解它的工作原理,以下是[]的实例:

instance HasEmpty [a] where
  empty = []
  isEmpty [] = True
  isEmpty _  = False

instance List [] where
  cons = (:)
  uncons (x:xs) = (x,xs)

但是,这会引发错误:

Not in scope: type variable 'a'

这是由约束HasEmpty (l a)引起的。我并不是对这个特殊的例子非常感兴趣,但我对这个概念感兴趣。 HasEmpty是类型*的类,而List是类型* -> *的类。 我是否可以创建一个与它所约束的类型类不同的类型类约束?

2 个答案:

答案 0 :(得分:3)

在任何情况下,您总是可以使用多参数类型类来表达基础逻辑(实际上它是在ListLike中完成的):

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

class HasEmpty a where
  empty :: a
  isEmpty :: a -> Bool

class HasEmpty (l a) => List l a where
  cons :: a -> l a -> l a
  uncons :: l a -> (a, l a)


instance HasEmpty [a] where
  empty = []
  isEmpty [] = True
  isEmpty _  = False

instance List [] a where
  cons = (:)
  uncons (x:xs) = (x,xs)

或者更优雅地通过类型系列:

{-# LANGUAGE TypeFamilies #-}

class HasEmpty a where
  empty :: a
  isEmpty :: a -> Bool


class HasEmpty a => List a where
  type Elem a :: *
  cons :: Elem a -> a -> a
  uncons :: a -> (Elem a, a)


instance HasEmpty [a] where
  empty = []
  isEmpty [] = True
  isEmpty _  = False


instance List [a] where
  type Elem [a] = a
  cons = (:)
  uncons (x:xs) = (x,xs)

答案 1 :(得分:2)

当然可以。例如。这对于相同的两个类都可以正常工作:

class HasEmpty (l ()) => List l where
  cons :: a -> l a -> l a
  uncons :: l a -> (a, l a)

或(其中List1 :: (* -> *) -> * -> *

class HasEmpty1 (l a) => List1 l a where
  cons :: a -> l a -> l a
  uncons :: l a -> (a, l a)

您不能做的是在约束中添加新变量。