Haskell

歷史

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

Haskell 1.0至1.4

1990年定義了Haskell的第一個版本（「Haskell 1.0」）。委員會形成了一系列的語言定義（1.0，1.1，1.2，1.3，1.4）。

Haskell 98

1997年底，該系列形成了Haskell 98，旨在定義一個穩定、最小化、可移植的語言版本以及相應的標準庫，以用於教學和作為將來擴充的基礎。委員會明確歡迎建立各種增加或整合實驗性特性的Haskell 98的擴充和變種。
1999年2月，Haskell 98語言標準公布，名為《The Haskell 98 Report》。2003年1月，《Haskell 98 Language and Libraries: The Revised Report》公布。接著，Glasgow Haskell Compiler (GHC)實現了當時的事實標準，Haskell快速發展。

Haskell Prime

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

Haskell 2010

Haskell 2010加入了外部函式介面（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是現有的一門開放的、已發布標準的，且有多種實現的語言。支援惰性求值、模式符合、列表解析、類型類和類型多型。它是一門純函式程式語言，這意味著大體上，Haskell中的函式沒有副作用。Haskell用特定的類型來表達副作用，該類型與函式類型相互獨立。純函式可以操作並返回可執行的副作用的類型，但不能夠執行它們，只有用於表達副作用的類型才能執行這些副作用，Haskell以此表達其它語言中的非純函式。
Haskell擁有一個基於Hindley-Milner類型推論的靜態、強型別系統。Haskell在此領域的主要創新就是加入了類型類（type class），原本設想作為多載的主要方式，在之後發現了更多用途。
Haskell的主要實現GHC是個直譯器，也是個原生程式碼編譯器。它可以在大多數平台執行，GHC在並行和並列上具有高效能的實現能力，也有豐富的型別系統，如廣義代數資料類型和類型族（Type Families）。
單子是一個抽象類型，可以表達不同種類的計算，包括例外處理、非確定性、語法分析以及軟體事務記憶體，其中一個應用是用於表達副作用的類型。單子定義為普通的資料類型，同時Haskell也為其提供了幾種語法糖。
Haskell有一個活躍的社群，線上上包倉庫Hackage上有豐富的第三方開源庫或工具。

資料類型

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

控制結構

if then else是分段函式定義時的語法糖。與C語言不同，要求必須有else部分。類似於C語言分支語句的情形，叫做pattern matching，例子如下：
 1 pts :: Int -> Int 2 pts 1 = 10 3 pts 2 = 6 4 pts x 5     | x <= 6    = 7 - x 6     | otherwise = 0 7  8 (||) :: Bool -> Bool -> Bool  -- 或操作的类型与定义 9 True  || _ = True             -- 第二个参数是任何值都匹配。 10 False || y = y

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)

例外處理

提供了處理異常的函式///.  
 1 import Prelude hiding(catch) 2 import Control.Exception 3 instance Exception Int 4 instance Exception Double 5 main = do 6   catch 7     (catch 8       (throw (42::Int)) 9       (\e-> print (0,e::Double)))10     (\e-> print (1,e::Int))
輸出結果
(1,42)
類似於 C++
 1 #include <iostream> 2 using namespace std; 3 int main() { 4     try { 5         throw (int)42; 6     } catch (double e) { 7         cout << "(0," << e << ")" << endl; 8     } catch (int e) { 9         cout << "(1," << e << ")" << endl;10     }11 }
另外一個例子：
1 do {2   -- Statements in which errors might be thrown3 } `catch` \ex -> do {4   -- Statements that execute in the event of an exception, with 'ex' bound to the exception5 }
如果僅有一個錯誤條件， 類足夠用了，確省是Haskell的  class. 更複雜的出錯處理用 或 monads, 類似功能可用。

Haskell的函式結構

如下是Haskell語言的"Hello world"，注意其中除最後一行外皆可省略。
1 module Main where2 3 main :: IO ()4 main = putStrLn "Hello, World!"
如下是階乘函式的Haskell實現：
1 fac :: Int -> Int2 fac 0 = 13 fac n = n * fac (n - 1)
它將階乘描述成有一個基本終止情形的遞迴函式。這跟數學定義中對階乘的描述很相似。事實上，Haskell中很多的程式碼的語法與功能都和數學一致。
上面的遞迴函式的第一行是可選的，它描述了這個函式的型態（types）。它可以讀作函式fac的型態為整數至整數（function fac has a int-to-int type）。這就是說，它以一個整型為參數，並且返回另一個整型。
第二行依賴的模式符合，是Haskell程式中一個重要的部分。注意函式的參數是用空格分隔而不是在括號中。當函式的參數是0時，它會返回整型1。對於其他的情況則嘗試第三行。這是一個遞迴，它會一直執行只到滿足基本的情形。負參數會導致無限遞迴，一個guard保證第三行不會執行負參數。
"Prelude"是一個類似C中標準庫的小函式集合。使用Prelude，並用無指定參數的寫法，它可以改成：
1 fac = product . enumFromTo 1
上面的定義接近於數學中的定義：f = g o h（參見複合函式），這並不是一個對變數賦值的語句。

Haskell的高階函式

Haskell中可以定義高階函式（Higher-order Function），既將函式作為一個參數來使用，也可以將函式作為結果輸出，例如：
1 f :: (Int -> Int) ->(Int -> Int)2 f g = \x -> g x + 5
這裡f就是一個高階函式，它取一個從Int到Int的函式g作為參數，輸出一個從Int到Int的函式。高階函式的使用在一些情況下將極大的簡化程式碼。