[英]Typeclass constraint of different kind
我一直在擺弄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 (la)
引起的。 我並不是對這個特殊的例子非常感興趣,但我對這個概念感興趣。 HasEmpty
是類型*
的類,而List
是類型* -> *
。 我是否有可能創建一個與它所約束的類型類不同的類型類約束?
在任何情況下,您總是可以使用多參數類型類來表達底層邏輯(實際上它是在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)
當然可以。 例如,這將適用於相同的兩個類:
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)
你不能做的是在約束中添加新變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.