差別聯合型別代表固定數量的具名案例。差別聯合的每個值都恰好對應其中一個具名案例。
差別聯合使用type關鍵字定義,各案例之間以管道(|)字元分隔:
type Season =
| Spring
| Summer
| Autumn
| Winter
差別聯合的每個案例都可以選擇性地帶有關聯資料,而且不同的案例可以帶有不同型態的資料。如果所有案例都沒有關聯資料,這個差別聯合就類似於其他語言通常所說的_列舉_。
type Number =
| Integer of int
| Float of float
| Invalid
建立特定案例的值,可以藉由參照它的名稱來完成(例如Success)。由於案例名稱就只是建構函式,關聯資料可以像一般函式引數一樣傳入。如果另一個差別聯合定義了同名的案例,你就必須使用它的完整名稱(例如Result.Success)。
let byName = Integer 2
let byFullName = Number.Invalid
差別聯合具有_結構相等性_,也就是說,同一個案例且帶有相同(選用)資料的兩個值彼此等價。
雖然你可以使用if/elif/else運算式來處理差別聯合,但建議的處理方式是透過模式比對,並使用_識別碼模式_:
let describe number =
match number with
| Integer i -> sprintf "Integer: %d" i
| Float d -> sprintf "Float: %f" d
| Invalid -> "Invalid"
在這個練習中,情人節到了,你和你的另一半打算一起做點開心的事。你的另一半有很多想法,現在要你為這些想法評分,好找出要進行的活動。
你的另一半提出了以下幾個想法:
你有 6 項任務,幫助你挑選情人節的活動。
你的另一半每提出一個想法,你都要從三種選項中擇一回應:「是」、「否」或「也許」。
定義Approval差別聯合,用下列 3 個案例來表示這些選項:Yes、No和Maybe。
你的另一半選了 2 間可能的餐廳:其中一間是韓式料理,另一間是土耳其料理。
定義Cuisine差別聯合,用下列 2 個案例來表示這些料理種類:Korean和Turkish。
可以選的電影多到數不清,所以為了縮小範圍,你的另一半也列出了自己想看的類型。
定義Genre差別聯合,用下列幾個案例來表示這些類型:Crime、Horror、Romance和Thriller。
如前所述,你的另一半想出了 5 種不同的活動:玩桌遊、放鬆一下、看電影、上餐廳吃飯和散步。
定義Activity差別聯合,用下列案例來表示這些活動類型:
BoardGame:沒有附帶資料。Chill:沒有附帶資料。Movie:以Genre作為附帶資料。Restaurant:以Cuisine作為附帶資料。Walk:以int作為附帶資料,代表要走的公里數。最後,你準備好要為另一半的想法評分了。以下是你對每個想法的感受:
實作一個名為rateActivity的函式,它接收一個Activity值,並根據上述的感受回傳對應的Approval:
rateActivity (Restaurant Turkish)
// => Maybe