Haskell

函數式編程語言

Haskell(發音為/ˈhæskəl/[26]是一種標準化的,通用的純函數式程式語言,有惰性求值靜態類型[27]。它的命名源自美國邏輯學家哈斯凱爾·加里,他在數理邏輯方面上的工作使得函數式程式設計語言有了廣泛的基礎。在Haskell中,「函數是頭等物件[28]。作為一門函數程式語言,主要控制結構是函數。Haskell語言是1990年在程式語言Miranda語言的基礎上標準化的,並且以λ演算為基礎發展而來。這也是為什麼Haskell語言以希臘字母λ」(Lambda)作為自己的標誌。Haskell具有「證明即程式、命題為類型」的特徵[29][30][31][32]

Haskell
Haskell的徽標
編程範型純函數式
設計者Lennart Augustsson英語Lennart Augustsson, Dave Barton, Brian Boutel, Warren Burton, Joseph Fasel, Kevin Hammond, Ralf Hinze, 保羅·胡達客, John Hughes英語John Hughes (computer scientist), Thomas Johnsson, Mark Jones, 西蒙·佩頓·瓊斯, John Launchbury英語John Launchbury, Erik Meijer英語Erik Meijer (computer scientist), John Peterson, Alastair Reid, Colin Runciman, 菲利普·瓦德勒
釋出時間1990年,​34年前​(1990[1]
目前版本
  • Haskell 2010(2010年7月)[2]
編輯維基數據連結
型態系統推論, 靜態, 強型別
作業系統跨平臺
副檔名.hs, .lhs
網站www.haskell.org
主要實作產品
GHC, Hugs英語Hugs, NHC, JHC, Yhc
啟發語言
Clean,[3] FP,[3] Gofer英語Gofer (programming language),[3] Hope和Hope+,[3] Id英語Id (programming language),[3] ISWIM,[3] KRC,[3] Lisp,[3] Miranda,[3] MLStandard ML,[3] Orwell英語Orwell (programming language), SASL,[3] Scheme,[3] SISAL[3]
影響語言
Agda,[4] Bluespec英語Bluespec,[5] C++11/Concepts,[6] C#/LINQ,[7][8][9][10] Cayenne,[7] Clean,[7] Clojure,[11] CoffeeScript,[12] Curry,[7] Elm, Escher英語Escher (programming language),[13] F#,[14] Frege,[15] Hack,[16] Idris,[17] Isabelle,[7] Java/Generics,[7] LiveScript英語LiveScript,[18] Mercury,[7] PureScript,[19] Python,[7][20] Raku,[21] Rust,[22] Scala,[7][23] Swift,[24] Timber,[25] Visual Basic 9.0[7][8]

歷史

1985年,Miranda發行後,惰性函數式語言的關注度增長。到1987年前,出現了十多種非限定性英語Strict function、純函數式語言。其中,Miranda使用的最為廣泛,但還沒有出現在公共領域。在俄勒岡波特蘭的函數式程式設計語言與電腦結構大會(FPCA '87)上,參加者一致同意形成一個委員會來為這樣的語言定義一種開源標準。該委員會旨在整合已有函數式語言,作為將來的函數式語言設計研究工作的基礎。[33]

Haskell 1.0至1.4

能夠確使類型安全運算子多載類型類,是由Philip Wadler和Stephen Blott最初為Standard ML提議的,但首先在Haskell中於1987年至版本1.0期間實現[34][35]

1990年定義了Haskell的第一個版本(「Haskell 1.0」)。[36]委員會形成了一系列的語言定義(1.0,1.1,1.2,1.3,1.4)。

 
在GHC 7.10的Haskell prelude中的類型類層級。包括了Foldable和Traversable(相應的改變了一些函數的類型簽章),和作為FunctorMonad中介的Applicative,它們出自Haskell 2010標準。

Haskell 98

1997年底,該系列形成了Haskell 98,旨在定義一個穩定、最小化、可移植的語言版本以及相應的標準庫,以用於教學和作為將來擴充的基礎。委員會明確歡迎建立各種增加或整合實驗性特性的Haskell 98的擴充和變種。[33]

1999年2月,Haskell 98語言標準公佈,名為《The Haskell 98 Report》。[33]2003年1月,《Haskell 98 Language and Libraries: The Revised Report》公佈。[37]接着,格拉斯哥Haskell編譯器實現了當時的事實標準,Haskell快速發展。

Haskell Prime

2006年早期,開始了定義Haskell 98標準後續的行程,非正式命名為Haskell Prime[38]這是個修訂語言定義的不斷增補的過程,每年產生一個新的修訂版。第一個修訂版於2009年11月完成、2010年7月發佈,稱作Haskell 2010

Haskell 2010

Haskell 2010加入了外部函數介面(Foreign Function Interface英語Foreign Function Interface,FFI)允許繫結到其它程式語言,修正了一些語法問題(在正式語法中的改動)並廢除了稱為「n加k模式」(換言之,不再允許形如fact (n+1) = (n+1) * fact n的定義)。引入了語言級編譯選項語法擴充(Language-Pragma-Syntax-Extension),使得在Haskell原始碼中可以明確要求一些擴充功能。Haskell 2010引入的這些擴充的名字是DoAndIfThenElse、HierarchicalModules、EmptyDataDeclarations、FixityResolution、ForeignFunctionInterface、LineCommentSyntax、PatternGuards、RelaxedDependencyAnalysis、LanguagePragma、NoNPlusKPatterns。

特性

Haskell是現有的一門開放的、已發佈標準的,且有多種實現的語言。[37]支援惰性求值模式匹配列表解析類型類類型多型。它是一門純函數式程式設計語言,這意味着大體上,Haskell中的函數沒有副作用。Haskell用特定的類型來表達副作用,該類型與函數類型相互獨立。純函數可以操作並返回可執行的副作用的類型,但不能夠執行它們,只有用於表達副作用的類型才能執行這些副作用,Haskell以此表達其它語言中的非純函數。

Haskell擁有一個基於Hindley-Milner類型推論靜態強型別系統。Haskell在此領域的主要創新就是加入了類型類,原本設想作為多載的主要方式,[39]在之後發現了更多用途。[40]

Haskell的主要實現GHC是個直譯器,也是個原生代碼編譯器。它可以在大多數平台執行,GHC在並行和並列上具有高效能的實現能力,[41]也有豐富的型別系統,如廣義代數資料類型英語Generalized algebraic data type類型家族英語Type family)。

單子是一個抽象類型,可以表達不同種類的計算,包括例外處理非確定性語法分析以及軟件事務主記憶體,其中一個應用是用於表達副作用的類型。單子定義為普通的資料類型,同時Haskell也為其提供了幾種語法糖

Haskell有一個活躍的社區,線上上包倉庫Hackage上有豐富的第三方開源庫或工具。[42]

語法

資料類型

Haskell是強型別語言。Char的字面值用單引號圍起;字串即[Char]類型,其字面值用雙引號括起來。Int通常為32位元整型;Integer是無界整型;Float 表示單精度的浮點數;Double 表示雙精度的浮點數;Bool 只有兩種值:True 和 False。

List

使用[ ]與逗號分隔符,定義一個list的實例。其元素必須具有相同類型。字串是list的特例。用:把元素與list、其他元素連接(cons)起來。:是右結合的運算子。[1,2,3] 實際上是 1:2:3:[] 的語法糖。兩個 List 合併通過 ++ 運算子實現。按照索引取得 List 中的元素,可以使用 !! 運算子,索引的下標為 0。List 中的 List 可以是不同長度,但必須得是相同的型別。['K'..'Z']這樣的Range方法快捷定義一個List。[2,4..20]用法給出了Range的第一、第二、最後一個元素。使用 > 和 >= 可以比較 List 的大小。它會先比較第一個元素,若它們的值相等,則比較下一個,以此類推。List常用的函數:

  • head 返回一個 List 的頭部,也就是 List 的首個元素。
  • tail 返回一個 List 的尾部,也就是 List 除去頭部之後的部分。
  • last 返回一個 List 的最後一個元素。
  • init 返回一個 List 除去最後一個元素的部分。
  • length 返回一個 List 的長度。
  • null 檢查一個 List 是否為空。如果是,則返回 True,否則返回 False。
  • reverse 將一個 List 反轉
  • take 返回一個 List 的前幾個元素。例如take 24 [13,26..]取前24個13的倍數
  • drop 刪除一個 List 中的前幾個元素
  • maximum 返回一個 List 中最大的元素。
  • minimun 返回最小的元素。
  • sum 返回一個 List 中所有元素的和。
  • product 返回一個 List 中所有元素的積。
  • elem 判斷一個元素是否在包含於一個 List,通常以中綴函數的形式呼叫
  • replicate 得到包含相同元素的 List 。例如:replicate 3 10,得 [10,10,10]。
  • repeat 產生一個元素的無限重複的List
  • cycle 接受一個 List 做參數並返回一個無限 List

list comprehension是指基於一個List,按照規則產生一個新List,例如:[x*2 | x <- [1..10], x*2 >= 12]

Tuple

使用( )與逗號分隔符,定義一個tuple的實例。其元素可以使不同類型,但個數是固定的。

Tuple的類型取決於其中項的數目與其各自元素的類型。單元素的 Tuple 被禁止。

  • fst 返回一個序對的首項。
  • snd 返回序對的尾項
  • zip 取兩個 List作為參數,然後將它們依次配對,形成一組序對的 List。

運算子

基本類似於C語言。但使用not表示邏輯非。

 +  -  *  /  ^    -- 加、減、乘、除、指數
 mod              -- 取餘數
 $                -- 也是表示函數作用的, 但它的優先級最低, 而且作用次序是從右向左的
 ++               -- 兩個List的連接
 .                 -- 函數的複合
 && ||  ==  /=     -- 與、或、等於、不等於
 <=  >=  <  >      -- 小於等於、大於等於、小於、大於
 : //  =  @        -- 一個元素連接List、
 ->               -- 函數類型描述,運算符左邊為參數類型,右邊為結果類型。為右结合。例如:addThree :: Int -> Int -> Int -> Int 
 =>               -- 運算符的左邊表示一個類型變量(通常為單個小寫字母)屬於一個類型類(Typeclass),相當於C++語言的模板參數類型
 ..               -- List的Range限定
 ::               -- 函數/表達式的類型特徵,左側為函數/表達式,右側為類型
 <-             -- List comprehension 的條件限定
 !!             -- 取List的第某個元素,下標從0開始

基本的 Typeclass:

  • Eq 可判斷相等性的type
  • Ord 可比較大小的type
  • Show 可表示為字串的type
  • Read 可從字串轉換出值的type
  • Enum 連續的,也就是可列舉的type。每個值都有後繼 (successer) 和前置 (predecesor),分別可以通過 succ 函數和 pred 函數得到。
  • Bounded 有上限和下限。例如:maxBound :: Char 或者 maxBound :: Bool
  • Num 數字
  • Integral
  • Floating

表達式

  • let表達式:格式為 let [bindings] in [expressions] 。let 也可以定義局部函數 。在一行中設定多個名字的值,可用分號隔開。List Comprehension 中 let繫結的名字在輸出函數及限制條件中都可見;忽略了 let 繫結的 in 部分,因為名字的可見性已經預先定義好了。
  • if then else是表達式
  • Case表達式:
 case expression of pattern -> result  
      pattern -> result  
      pattern -> result  
      ...  

控制結構

if then else是分段函數定義時的語法糖。與C語言不同,要求必須有else部分。類似於C語言分支陳述式的情形,叫做pattern matching,例子如下:

pts :: Int -> Int
pts 1 = 10
pts 2 = 6
pts x
    | x <= 6    = 7 - x
    | otherwise = 0

(||) :: Bool -> Bool -> Bool  -- 或操作的类型与定义
True  || _ = True             -- 第二个参数是任何值都匹配。 
False || y = y

函數

  • 函數呼叫有最高運算順序,例如succ 9*10表示(succ 9)*10
  • 函數的呼叫使用空格符而不是括號。
  • 函數的複合呼叫是左結合。
  • 首字母大寫的函數是不允許的。
  • 兩個參數的函數的呼叫可以寫成中綴形式:param1 `funcName` param2
  • 運算子可以用括號圍起來,作為字首形式:(+) 2 3 的結果為5。
  • 在 ghci 下,我們可以使用 let 關鍵字來定義一個常數。在 ghci 下執行 let a=1 與在指令碼中編寫 a=1 是等價的。
--funcName arguments = expression  --定义函数的一般形式
area r = pi * r ^ 2 -- 定义了一个函数
area 101 -- 调用了函数
f1 f2 3.14 -- 函数调用是左结合,等效于(f1 f2) 3.14

--模式匹配方式定义
factorial :: (Integral a) => a -> a  
factorial 0 = 1  
factorial n = n * factorial (n - 1)   

--as模式,是将一个名字和 @ 置于模式前,可以在按模式分割参数值时仍保留对其整体的引用。如nameGlobal@(x:y:ys),nameGlobal会匹配出与 x:y:ys 对应的东西。as模式在较大的模式中保留对整体的引用,从而减少重复性的工作。

heron a b c = sqrt (s * (s - a) * (s - b) * (s - c))
    where                     -- where在表达式中局部绑定了名字s与一个值。也可以在表达式之前用let ... in语法
    s = (a + b + c) / 2

absolute x                 -- 绝对值函数,使用了分段函数语法糖(称作Guards)
    | x < 0     = 0 - x
    | otherwise = x        -- 兜底条件

bmiTell :: (RealFloat a) => a -> a -> String  
bmiTell weight height  
    | bmi <= 18.5 = "You're underweight."  
    | bmi <= 25.0 = "You're normal. "  
    | bmi <= 30.0 = "You're fat."  
    | otherwise   = "You're overweight."  
    where bmi = weight / height ^ 2  -- 使用where定义多个名字来避免重复

--where也可以用模式匹配
initials :: String -> String -> String  
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."  
    where (f:_) = firstname  
          (l:_) = lastname  

--where可以定义函数。在定义一个函数的时候也写几个辅助函数摆在 where 绑定中。 而每个辅助函数也可以透过 where 拥有各自的辅助函数。
calcBmis :: (RealFloat a) => [(a, a)] -> [a]  
calcBmis xs = [bmi w h | (w, h) <- xs] 
    where bmi weight height = weight / height ^ 2  

funcName :: type1 -> type2 -> type3 -- 其中,::表示类型特征(type signature),->是右结合,这里等效于type1 -> (type2->type3),给定一个type1的输入参数,返回一个函数(type2->type3)

f1 = (absolute .  area)   -- 函数复合运算符是 . (function composition operator)

多型類型(Polymorphic types)類似於C++的模板。例如,算術加法:

 (+) :: (Num a) => a -> a -> a -- Num是typeclass。 =>表示signature restricts

lambda函數

lambda 就是匿名函數。寫法是:一個 \(因為它看起來像是希臘字母λ),後面是用空格分隔的參數,-> 後面是函數體。通常用括號將括起lambda函數,否則它會佔據整個右邊部分。

例如:(\a b -> (a * 30 + 3) / b)

可以在 lambda 中使用模式匹配,但無法為一個參數設置多個模式,如 [](x:xs) 並用。

使用 lambda 可以更明確地表現出值是個函數,可以用來傳遞給其他函數作參數。

高階函數

Haskell的所有函數實際上是單參數函數。多參數函數的寫法實際上是Curry化的語法糖。即 func a b 等價於 (func a) b

point free style (也稱作 pointless style) 的函數,即通過柯里化 (Currying)省略掉單參數。例如:

 sum' :: (Num a) => [a] -> a     
 sum' xs = foldl (+) 0 xs   --等号的两端都有个 xs。 
 sum'   = foldl (+) 0     --柯里化 (Currying),可以省掉两端的 xs。

中綴運算子可以加括號變為單參數函數。如 (*3) 5 的值為15。 但 (-5) 表示負值,所以單參數函數需要寫為 (subtract 5)

中綴運算子 $ 可用於改變函數的呼叫次序,使其右邊的表達式先計算出來。這可以減少一對括號使用。例如 f (g (z x))f $ g $ z x 等價。其定義是:

 ($) :: (a -> b) -> a -> b  
 f $ x = f x

$ 還可以將數據作為函數使用。例如:

 map ($ 3) [(4+),(10*),(^2),sqrt]

中綴運算子 . 用於函數的複合,其定義是:

 (.) :: (b -> c) -> (a -> b) -> a -> c  
 f . g = \x -> f (g x)

例外處理

提供了處理異常的函數trycatchfinally/etc.

import Prelude hiding(catch)
import Control.Exception
instance Exception Int
instance Exception Double
main = do
  catch
    (catch
      (throw (42::Int))
      (\e-> print (0,e::Double)))
    (\e-> print (1,e::Int))

輸出結果

(1,42)

類似於 C++

#include <iostream>
using namespace std;
int main() {
    try {
        throw (int)42;
    } catch (double e) {
        cout << "(0," << e << ")" << endl;
    } catch (int e) {
        cout << "(1," << e << ")" << endl;
    }
}

另外一個例子:

do {
  -- Statements in which errors might be thrown
} `catch` \ex -> do {
  -- Statements that execute in the event of an exception, with 'ex' bound to the exception
}

如果僅有一個錯誤條件,Maybe 類足夠用了,確省是Haskell的 Monad class. 更複雜的出錯處理用ErrorErrorT monads, 類似功能可用`catch`

範例

Haskell的函數結構

如下是Haskell語言的"Hello world",注意其中除最後一行外皆可省略。

module Main where

main :: IO ()
main = putStrLn "Hello, World!"

如下是階乘函數的Haskell實現:

fac :: Int -> Int
fac 0 = 1
fac n = n * fac (n - 1)

它將階乘描述成有一個基本終止情形的遞歸函數。這跟數學定義中對階乘的描述很相似。事實上,Haskell中很多的代碼的語法與功能都和數學一致。

上面的遞歸函數的第一行是可選的,它描述了這個函數的型態types)。它可以讀作函數fac的型態為整數至整數(function fac has a int-to-int type)。這就是說,它以一個整型為參數,並且返回另一個整型。

第二行依賴的模式匹配,是Haskell程式中一個重要的部分。注意函數的參數是用空格分隔而不是在括號中。當函數的參數是0時,它會返回整型1。對於其他的情況則嘗試第三行。這是一個遞歸,它會一直執行只到滿足基本的情形。負參數會導致無限遞歸,一個guard英語guard (computing)保證第三行不會執行負參數。

"Prelude"是一個類似C中標準庫的小函數集合。使用Prelude,並用無指定參數的寫法,它可以改成:

fac = product . enumFromTo 1

上面的定義接近於數學中的定義:f = g o h(參見複合函數),這並不是一個對變數賦值的陳述式。

Haskell的高階函數

Haskell中可以定義高階函數(Higher-order Function),既將函數作為一個參數來使用,也可以將函數作為結果輸出,例如:

f :: (Int -> Int) ->(Int -> Int)
f g = \x -> g x + 5

這裏f就是一個高階函數,它取一個從Int到Int的函數g作為參數,輸出一個從Int到Int的函數。高階函數的使用在一些情況下將極大的簡化代碼。

Haskell的編譯器

參考文獻

  1. ^ Hudak et al. 2007.
  2. ^ [Haskell] Announcing Haskell 2010. 2009年11月24日 [2023年1月11日]. 
  3. ^ 3.00 3.01 3.02 3.03 3.04 3.05 3.06 3.07 3.08 3.09 3.10 3.11 3.12 Peyton Jones 2003,第xi頁
  4. ^ Norell, Ulf. Dependently Typed Programming in Agda (PDF). Gothenburg: Chalmers University. 2008 [9 February 2012]. (原始內容 (PDF)存檔於2014-04-01). 
  5. ^ Hudak et al. 2007,第12–38, 43頁.
  6. ^ Stroustrup, Bjarne; Sutton, Andrew. Design of Concept Libraries for C++ (PDF). 2011. (原始內容 (PDF)存檔於10 February 2012). 
  7. ^ 7.00 7.01 7.02 7.03 7.04 7.05 7.06 7.07 7.08 7.09 Hudak et al. 2007,第12-45–46頁.
  8. ^ 8.0 8.1 Meijer, Erik. Confessions of a Used Programming Language Salesman: Getting the Masses Hooked on Haskell. Oopsla 2007. 2006. 
  9. ^ Meijer, Erik. C9 Lectures: Dr. Erik Meijer – Functional Programming Fundamentals, Chapter 1 of 13. Channel 9. Microsoft. 1 October 2009 [9 February 2012]. (原始內容存檔於2012-06-16). 
  10. ^ Drobi, Sadek. Erik Meijer on LINQ. InfoQ (QCon SF 2008: C4Media Inc.). 4 March 2009 [9 February 2012]. (原始內容存檔於2021-01-26). 
  11. ^ Hickey, Rich. Clojure Bookshelf. Listmania!. [3 October 2017]. (原始內容存檔於3 October 2017). 
  12. ^ Heller, Martin. Turn up your nose at Dart and smell the CoffeeScript. InfoWorld. 2011-10-18 [2020-07-15]. (原始內容存檔於2021-01-25). 
  13. ^ Declarative programming in Escher (PDF). [7 October 2015]. (原始內容 (PDF)存檔於2016-03-03). 
  14. ^ Syme, Don; Granicz, Adam; Cisternino, Antonio. Expert F#. Apress. 2007: 2. F# also draws from Haskell particularly with regard to two advanced language features called sequence expressions and workflows. 
  15. ^ Wechsung, Ingo. The Frege Programming Language (PDF). [26 February 2014]. (原始內容 (PDF)存檔於2021-02-13). 
  16. ^ Facebook Introduces 'Hack,' the Programming Language of the Future. WIRED. 20 March 2014 [2021-02-28]. (原始內容存檔於2014-03-28). 
  17. ^ Idris, a dependently typed language. [26 October 2014]. (原始內容存檔於2021-05-11). 
  18. ^ LiveScript Inspiration. [4 February 2014]. (原始內容存檔於2021-05-21). 
  19. ^ Freeman, Phil. PureScript by Example. Leanpub. 2016 [23 April 2017]. (原始內容存檔於2020-11-29). 
  20. ^ Kuchling, A. M. Functional Programming HOWTO. Python v2.7.2 documentation. Python Software Foundation. [9 February 2012]. (原始內容存檔於2012-10-24). 
  21. ^ Glossary of Terms and Jargon. Perl Foundation Perl 6 Wiki. The Perl Foundation. [9 February 2012]. (原始內容存檔於21 January 2012). 
  22. ^ The Rust Reference: Appendix: Influences. [3 February 2016]. (原始內容存檔於2019-01-26). 
  23. ^ Fogus, Michael. MartinOdersky take(5) toList. Send More Paramedics. 6 August 2010 [9 February 2012]. (原始內容存檔於2012-02-14). 
  24. ^ Lattner, Chris. Chris Lattner's Homepage. Chris Lattner. 3 June 2014 [3 June 2014]. (原始內容存檔於2018-12-25). The Swift language is the product of tireless effort from a team of language experts, documentation gurus, compiler optimization ninjas, and an incredibly important internal dogfooding group who provided feedback to help refine and battle-test ideas. Of course, it also greatly benefited from the experiences hard-won by many other languages in the field, drawing ideas from Objective-C, Rust, Haskell, Ruby, Python, C#, CLU, and far too many others to list. 
  25. ^ Timber/History. [7 October 2015]. (原始內容存檔於2020-10-31). 
  26. ^ Chevalier, Tim. anybody can tell me the pronuncation of "haskell"?. Haskell-cafe (郵寄清單). 28 January 2008 [12 March 2011]. (原始內容存檔於2012-03-06). 
  27. ^ Haskell Report
  28. ^ Burstall, Rod. Christopher Strachey—Understanding Programming Languages. Higher-Order and Symbolic Computation. 2000, 13 (52). 
  29. ^ Curry, Haskell. Functionality in Combinatory Logic. Proceedings of the National Academy of Sciences 20. 1934: 584–590. 
  30. ^ Curry, Haskell B.; Feys, Robert. Craig, William , 編. Combinatory Logic Vol. I. Amsterdam: North-Holland. 1958. , with 2 sections by William Craig, see paragraph 9E
  31. ^ De Bruijn, Nicolaas. Automath, a language for mathematics. TH-report 68-WSK-05 (Department of Mathematics, Eindhoven University of Technology). 1968.  Reprinted in revised form, with two pages commentary, in: Classical papers on computational logic 1967-1970. Automation and Reasoning 2. Springer Verlag. 1983: 159–200. 
  32. ^ Howard, William A. The formulae-as-types notion of construction. Seldin, Jonathan P.; Hindley, J. Roger (編). To H.B. Curry: Essays on Combinatory Logic, Lambda Calculus and Formalism. Boston, MA: Academic Press英語Academic Press. 1980年9月: 479–490 [original paper manuscript from 1969]. ISBN 978-0-12-349050-6. .
  33. ^ 33.0 33.1 33.2 Preface. Haskell 98 Language and Libraries: The Revised Report. December 2002 [2012-08-26]. (原始內容存檔於2012-08-23). 
  34. ^ "Type classes, first proposed during the design of the Haskell programming language, ..." —John Garrett Morris (2013), "Type Classes and Instance Chains: A Relational Approach"頁面存檔備份,存於互聯網檔案館
  35. ^ Wadler, Philip. How to make ad-hoc polymorphism less ad hoc. October 1988. 
  36. ^ Hudak, Paul; Hughes, John; Peyton Jones, Simon; Wadler, Philip. A history of Haskell: being lazy with class. Proceedings of the third ACM SIGPLAN conference on History of programming languages(HOPL III). 2007: 12–1–12–55. ISBN 978-1-59593-766-7. doi:10.1145/1238844.1238856. 
  37. ^ 37.0 37.1 Simon Peyton Jones (editor). Haskell 98 Language and Libraries: The Revised Report. December 2002 [2012-08-26]. (原始內容存檔於2012-05-18). 
  38. ^ Welcome to Haskell'. The Haskell' Wiki. [2012年8月26日]. (原始內容存檔於2009年4月23日). 
  39. ^ Wadler, P.; Blott, S. How to make ad-hoc polymorphism less ad hoc. Proceedings of the 16th ACM SIGPLAN英語SIGPLAN-SIGACT英語SIGACT Symposium on Principles of Programming Languages英語Symposium on Principles of Programming Languages (ACM). 1989: 60–76. ISBN 0-89791-294-2. doi:10.1145/75277.75283. 
  40. ^ Hallgren, T. Fun with Functional Dependencies, or Types as Values in Static Computations in Haskell. Proceedings of the Joint CS/CE Winter Meeting (Varberg, Sweden). January 2001 [2012-08-26]. (原始內容存檔於2010-03-29). 
  41. ^ Computer Language Benchmarks Game. [2012-08-26]. (原始內容存檔於2018-05-29). 
  42. ^ 存档副本. [2013-06-26]. (原始內容存檔於2013-05-03). 

外部連結

教學手冊