我一直在摆弄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
是类型* -> *
的类。 我是否可以创建一个与它所约束的类型类不同的类型类约束?
答案 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)
您不能做的是在约束中添加新变量。