類型類

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

計算機科學中,類型類(type class),是支持特設多態類型系統構造。這是通過向參數多態類型的類型變量增加約束完成的。這種約束典型的涉及到一個類型類T和一個類型變量英語Type variablea,並意味着a所能實例化的類型,其成員必須支持關聯於T的重載運算。

類型類首先在Haskell中實現,當時Philip Wadler和Stephen Blott提出它,作為對Standard MLeqtype的擴展[1][2],並且最初構想為以本原方式實現重載算術及等式算符的一種途徑[3][4]。 對比於Standard ML的「eqtypes」,在Haskell中通過使用類型類重載等式算符,不要求編譯器前端或底層類型系統的廣泛修改[5]

自從它們創立之後,已經發現了類型類的很多其他應用。

概述[編輯]

定義類型類需要通過規定一組函數或約束名字,它們分別具有同在的類型,它們對屬於這個類的所有類型都必須存在。在Haskell中,類型可以被參數化,意圖包含允許等式的類型一個類型類Eq,可以如下這樣聲明:

class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool
  x /= y  =  not (x == y)
  x == y  =  not (x /= y)

這裡的a是類型類Eq的一個實例,並且a定義的函數簽名,針對了2個函數(等式和不等式函數),它們每個都接受2個類型a的實際參數並返回一個布爾值。這個聲明可以讀作:「類型a屬於類型類Eq,如果在其上定義了有適當類型的,叫做(==)(/=)的的函數。」

編程者可以使任何類型t成為給定類型類C 的成員,通過使用「實例聲明」 為特定類型t實現所有的C方法。如果編程者定義一個新的記錄數據類型Foo,可以接着使這個新類型成為Eq的實例,通過以任何他們認為合適的方式,提供在類型Foo的值之上的等式函數和不等式函數,例如:

data Foo = Foo {x :: Integer, str :: String}
 
instance Eq Foo where
   (Foo x1 str1) == (Foo x2 str2) = (x1 == x2) && (str1 == str2)

編程者可以接着如下這樣定義函數elem,它確定一個元素是否在一個列表之中:

elem :: Eq a => a -> [a] -> Bool
elem y []     = False
elem y (x:xs) = (x == y) || elem y xs

函數elem的類型a -> [a] -> Bool具有上下文Eq a,將參數多態函數的類型變量a可包括的類型,約束為屬於Eq類型類的那些類型。Haskell中的 => 可表示「類型類繼承」或「類型約束」。函數elem可應用於屬於Eg類型類的任何類型的元素和這個類型的列表二者之上。

注意類型類不同於面向對象編程語言中的。特別是,Eq不是一個類型:沒有類型Eq的值這種東西。類型變量a種類英語Kind (type theory)(kind),在最新的GHC發行中叫做Type[6]。意味着Eq的種類是:

Eq :: Type -> Constraint

高種類多態[編輯]

類型類不但接受種類英語Kind (type theory)Type的類型變量,它可以接受任何種類的類型變量。這些有更高種類的類型類有時叫做構造子類,這裡的構造子指稱的是類型構造子比如Maybe,而非數據構造子比如Just。例如單子Monad

class Monad m where
  return :: a -> m a
  (>>=)  :: m a -> (a -> m b) -> m b

m應用到一個類型變量上的事實,指出了它有着種類Type -> Type,就是說它接受一個類型並返回一個類型,因而Monad的種類是:

Monad :: (Type -> Type) -> Constraint

多參數類型類[編輯]

類型類允許多個類型參數,因此類型類可以被看作在類型上的關係[7]。例如,在GHC標準庫中,類IArray表達一個通用不可變數組接口。在這個類中,類型約束IArray a e意味着a是一個數組類型,它包含類型e的元素。例如,在多態上的這種限制被用來實現開箱英語Object type (object-oriented programming)#Unboxing數組類型。

函數依賴[編輯]

在Haskell中,類型類已經被精製為允許編程者聲明在類型參數之間的函數依賴,這個概念受到關係數據庫理論中的函數依賴的啟發[8][9]。就是說,編程者可以斷言對類型參數的某個子集的給定指派,唯一性的確定餘下的類型參數。例如,承載一個類型s的狀態參數的,一個一般性的單子m,滿足類型類約束Monad.State s m。在這個約束中,有函數依賴m -> s。這意味着對於類型類Monad.State的一個給定單子m,從m能訪問到的狀態類型是被唯一性確定的。這會輔助編譯器進行類型推論,還能輔助編程者進行類型導向編程。

Simon Peyton-Jones因其複雜性而反對在Haskell中介入函數依賴[10]

運算符重載的其他方式[編輯]

Standard ML中,「等式類型」的機制粗略的對應於Haskell的內建類型類Eq,但是所有等式算符都自動的由編譯器導出。編程者的過程控制局限於,指定在一個結構中哪些類型成員是等式類型,和在多態類型中哪些類型變量涉及等式類型。

SML和OCaml的模塊和函子可以扮演類似於Haskell的類型類的角色,原則區別在於類型推論的角色,它使得類型類適合於特設多態[11]OCaml的面向對象子集是某種程度上與類型類有可比性的另一種方式。

有關概念[編輯]

用於重載數據的一個類似概念(實現於GHC中)是類型家族英語type family[12]

Clean中的類型類與Haskell相似,但是有稍微不同的語法。

Rust支持trait,這是具有一致性的有限形式的類型類[13]

Mercury有類型類,卻不完全同於Haskell。

Scala中,類型類是編程慣例英語programming idiom,可以用現存語言特徵比如隱式參數來實現,本身不是獨立的語言特徵。由於它們在Scala中的這種實現方式,在有歧義的情況下,有可能顯式的指定哪種類型類實例用作在代碼中特定位置上的類型。但是,這不必然有益處,因為有歧義的類型類實例是易於出錯的。

證明輔助Coq在新近版本也支持類型類。不像在平常編程語言中那樣,在Coq中,在類型類定義內陳述的任何類型類定律(比如單子定律),在使用它們之前,必須對每個類型類實例進行數學證明。

參見[編輯]

引用[編輯]

  1. ^ Morris, John. Type Classes and Instance Chains (PDF). 2013 [2021-02-08]. (原始內容存檔 (PDF)於2020-11-04). 
  2. ^ Wadler, Philip. How to make ad-hoc polymorphism less ad hoc. October 1988. 
  3. ^ Kaes, Stefan. Parametric overloading in polymorphic programming languages. Proc. 2nd European Symposium on Programming Languages. March 1988. doi:10.1007/3-540-19027-9_9. 
  4. ^ Wadler, Philip; Stephen Blott. How to make ad-hoc polymorphism less ad hoc. Proc. 16th ACM Symposium on Principles of Programming Languages. January 1989 [2021-02-08]. (原始內容存檔於2016-03-11). 
  5. ^ Appel, Andrew; David MacQueen. Standard ML of New Jersey. Proc. 3rd International Symposium on Programming Language Implementation and Logic Programming. June 1991 [2021-02-08]. (原始內容存檔於2008-05-09). 
  6. ^ Type頁面存檔備份,存於網際網路檔案館) from Data.Kind appeared in version 8 of the Glasgow Haskell Compiler
  7. ^ Haskell' page MultiParamTypeClasses頁面存檔備份,存於網際網路檔案館.
  8. ^ Mark Jones. Type Classes with Functional Dependencies頁面存檔備份,存於網際網路檔案館. From Proc. 9th European Symposium on Programming. March, 2000.
  9. ^ Haskell' page FunctionalDependencies頁面存檔備份,存於網際網路檔案館.
  10. ^ 存档副本. [2021-02-10]. (原始內容存檔於2014-12-25). 
  11. ^ Dreyer, Derek; Robert Harper; Manuel M.T. Chakravarty. Modular Type Classes. April 2006 [2021-03-01]. (原始內容存檔於2007-05-19).  |book-title=被忽略 (幫助)
  12. ^ GHC/Type families - HaskellWiki. [2021-02-10]. (原始內容存檔於2014-10-28). 
  13. ^ Specialization, coherence, and API evolution · Aaron Turon. [2021-02-10]. (原始內容存檔於2020-11-12). 

外部連結[編輯]