代數資料型態(ADT)代表固定數量的具名情況。 ADT 的每個值都恰好對應到其中一個具名情況。
ADT 使用data關鍵字定義,各個情況之間以直立線(|)字元分隔。
如果所有情況都沒有附帶資料,這種 ADT 就類似其他語言通常所稱的列舉(或 enum)。
data Season
= Spring
| Summer
| Autumn
| Winter
ADT 的每個情況都可以選擇性地附帶資料,而且不同的情況可以有不同的資料型態。 當情況附帶資料時,就必須有建構子。
data Number
= NInt Int --'NInt' is the constructor for an Int Number.
| NFloat Float --'NFloat' is the constructor for an Float Number.
| Invalid --'Invalid' does not have data associated to it.
要為某個特定情況建立值,只要引用它的名稱即可(例如NInt 22)。
由於情況名稱本身只是建構子函式,附帶的資料可以像一般函式引數一樣傳入。
ADT 具有結構相等性,意思是同一個情況且附帶的(選用)資料也相同的兩個值,彼此是相等的。
雖然可以用if/else運算式來處理 ADT,但建議的做法是使用case敘述進行模式匹配:
add1 :: Number -> String
add1 number =
case number of
NInt i -> show (i + 1)
NFloat f -> show (f + 1.0)
Invalid -> error "Invalid input"
在這個練習中,今天是情人節,你正在規劃要和伴侶一起做什麼。你的伴侶有很多想法,並請你為這些想法評分,好找出最棒的活動。
以下是你的伴侶提出的想法:
你有六個任務,幫助你選出情人節的活動。
你的伴侶提出的每個想法,你都要用三種選項之一來回應:yes、no 或 maybe。
定義 Approval 代數資料型態,以下列三種案例來表示這些選項:Yes、No 或 Maybe。
你的伴侶選了兩間可能的餐廳:一間是韓國料理,另一間是土耳其料理。
定義 Cuisine 代數資料型態,以下列兩種案例來表示這兩間餐廳:Korean 或 Turkish。
可以選擇的電影非常多,所以為了縮小範圍,你的伴侶也列出了自己偏好的類型。
定義 Genre 代數資料型態,以下列幾個類型案例來表示:Crime、Horror、Romance 或 Thriller。
如前所述,你的伴侶想出了五種可能的活動:玩桌遊、放鬆一下、看電影、去餐廳吃飯和散步。
定義 Activity 代數資料型態來表示這些活動類型:
BoardGame:沒有附帶資料。Chill:沒有附帶資料。Movie:以 Genre 作為附帶資料。Restaurant:以 Cuisine 作為附帶資料。Walk:以 Int 作為附帶資料,代表要步行的公里數。最後,你準備好要為伴侶的想法評分了。 以下是你看待伴侶想法的感受:
實作一個名為 rateActivity 的函式,接受一個 Activity 值,並依據上述感受回傳 Approval。
例如:
rateActivity (Restaurant Turkish)
-- -> Maybe