[英]Typeclass constraint of different kind
I have been fiddling with general type classes for lists in Haskell. 我一直在摆弄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)
To give you an idea of how it might work, here are instances for []
: 为了让您了解它是如何工作的,这里是[]
实例:
instance HasEmpty [a] where
empty = []
isEmpty [] = True
isEmpty _ = False
instance List [] where
cons = (:)
uncons (x:xs) = (x,xs)
However, this raises an error: 但是,这会引发错误:
Not in scope: type variable 'a'
This is caused by the constraint HasEmpty (la)
. 这是由约束HasEmpty (la)
引起的。 I am not desperately interested in this particular example, but I am interested in the concept in general. 我并不是对这个特殊的例子非常感兴趣,但我对这个概念感兴趣。 HasEmpty
is a class for types of kind *
, while List
is a class for types of kind * -> *
. HasEmpty
是类型*
的类,而List
是类型* -> *
。 Is it possible for me to make a typeclass constraint of a different kind than the typeclass it is constraining? 我是否有可能创建一个与它所约束的类型类不同的类型类约束?
In any case you can always express underlying logic either using multiparameter typeclasses (as in fact it is done in ListLike ): 在任何情况下,您总是可以使用多参数类型类来表达底层逻辑(实际上它是在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)
Or more elegantly via type families: 或者通过类型系列更优雅:
{-# 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)
Of course you can. 当然可以。 Eg this will work fine for the same two classes: 例如,这将适用于相同的两个类:
class HasEmpty (l ()) => List l where
cons :: a -> l a -> l a
uncons :: l a -> (a, l a)
or (where List1 :: (* -> *) -> * -> *
) 或(其中List1 :: (* -> *) -> * -> *
)
class HasEmpty1 (l a) => List1 l a where
cons :: a -> l a -> l a
uncons :: l a -> (a, l a)
What you can't do is add new variables in constraints. 你不能做的是在约束中添加新变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.