分類彙整: FP

Haskell 筆記》Currying function

在一般 C-like 的程式語言裡,如果想寫一個函數把兩個整數相加,並傳回相加後的結果,通常會這樣寫:

int add(int a, int b) { 
    return a + b; 
}
function add(a, b) {
    return a + b;
}

但是在 Haskell 裡會這樣寫:

add :: Int -> Int -> Int
add a b = a + b

第一行的 add :: Int -> Int -> Int 是描述函數的型別,第二行的 add a b = a + b 是函數的主體。

我第一次看到這種寫法時,覺得這種寫法看起來很怪,尤其是第一行,為何前兩個參數的分隔符號是用 -> 呢?

Haskell 的 -> 符號的含義: -> 符號表示一個函數,這個函數接受左側型別的參數,並返回右側型別的值。

後來才明白這種寫法的奇妙之處,因為這個函數是一個柯里化函數 (Currying function)

先在 GHCi 裡輸入並執行這個函數:

:t:type 的縮寫,這個指令可以查看一個值的型別,這裡可以看到 x 的型別是 Int,add 函數的型別是:Int -> Int -> Int 。

當給 add 函數兩個整數時,會傳回兩數相加的結果,但是,我們可以嘗試只給 add 函數一個整數

由上圖可以看到,我只給 add 函數一個參數(8),並將回傳結果存到 f,然後查看 f 的型別,會發現 f 是一個函數,型別是:Int -> Int。

這裡的 f 是一個「接受一個 Int 參數並傳回一個 Int 值」的函數,f 會把傳給它的整數加 8,並回傳相加的結果。

如下圖所示,當給 add 函數兩個參數時,傳回一個 Int 值:

如下圖所示,只給 add 函數一個參數時,傳回一個函數:

Haskell 用這種語法描述函數,真的很精妙啊!

R 語言筆記》一切運算皆是函數調用

最近在讀《高級 R 語言編程指南》(Advanced R) 這本書,讀到第 6 章時,發現 R 的語法其實很有趣,有些 Lisp 的味道 🙂

在 R 裡頭:

  • 一切皆是物件 (object)
  • 一切運算皆是函數調用

所以像是四則運算 (+-*/) 等符號也是函數 (屬於 中綴函數)。

然後,我們可以像這樣使用四則運算符,讓四則運算符以 前綴函數 的方式調用:

> `+`(2, 3)
[1] 5
> `*`(5, `+`(2, 3))
[1] 25
>

接下來,我們可以來惡搞一下 R:

> `(` <- function(e) e + 1
> `*`(5, (3 + 2))
[1] 30
> (3 + 2)
[1] 6
> (3 * 2)
[1] 7
> 

惡搞完 ( 符號後,接下來玩弄一下 + 運算符… XDD:

> add <- `+`
> add(2, 3)
[1] 5
> add(2, 100)
[1] 102
> `+` <- function(e1, e2) {
+   x <- add(e1, e2)
+   if (x <= 87) {
+     x
+   } else {
+     x <- 87
+     cat("87分不能再高了!\n")
+     x
+   }
+ }
> 
> 2 + 3
[1] 5
> 5 + 81
[1] 86
> 2 + 100
87分不能再高了!
[1] 87
> 2 + 10000
87分不能再高了!
[1] 87
> 

根據維基百科上的描述,R 的語法結合了 S 語言與 Scheme,經過上述的惡搞法後,各位有沒有感受到 R 有一點點 Lisp 的 () 味道呢? XD (Lisp 粉絲不要戰我)