簡體   English   中英

不同種類的類型約束

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM