1. 程式人生 > 實用技巧 >F# 函數語言程式設計之 - unpacking/deconstruct

F# 函數語言程式設計之 - unpacking/deconstruct

原文 https://fsharpforfunandprofit.com/posts/overview-of-types-in-fsharp/

這個特性我覺得也比較新鮮,以前沒有見過,先看程式碼吧:

type Dollar = Dollar of int
let earn d:Dollar = d + 10 // Error

雖然只有兩行程式碼,但有不少值得說明的地方。

第一行,有兩個 Dollar, 但它們有不同的含義,也只能用在不同的地方。第一個 Dollar 是一個型別,而第二個 Dollar 不是型別而是 union case, 這裡只是故意重名,以便在兩種場合都能使用 Dollar 這個單詞。

因此,第二行程式碼裡的 Dollar 是型別,此時,第二行會報錯,因為型別 Dollar 不能與型別 int 直接相加。

我們把其中一個 Dollar 改成別的單詞,就可以看得更清楚:

type Money = Dollar of int
let earn d:Dollar = d + 10  // Error

這樣,由於第一個 Dollar 已經改成 Money, 因此 Dollar 再也不能當作型別來使用,第二行會報錯,而這次的錯誤原因是 “Dollar 不是型別”。

再看下面的程式碼:

type Dollar = Dollar of int
let earn (Dollar d) = d + 10 // OK

上面的程式碼,第二行,就用到了我說的新鮮特性,這裡的 Dollar 不是型別,而是 union case, 同時,由於 union case 可以用於 pattern match, 根據 pattern match 的原理,(Dollar d)

正是一個 pattern, 即 (Dollar int), 因此,d 的型別就是 int.

由於 d 的型別是 int, 因此可以與 10 相加,這次程式碼不會報錯。

值得一提的是,這裡發生 pattern match 的地方是一個函式的引數!

更神奇的是,這裡 (Dollar int) 同時兼具兩個作用:

  1. 限定了該引數的型別是 Dollar, 如果輸入一個 int 或別的型別,會報錯,從而確保了型別安全。

  2. unpacking/deconstruct, “順便” 從這個引數裡把 Dollar 的內涵資料 int 給解構出來了。

本文介紹了 F# 的一個有趣的特性(unpacking/deconstruct), 該特性表面上看著簡單,背後卻涉及 type 與 union case 的區別,以及 pattern match 的用法。