寶箱

寶箱

學習練習

簡介

泛型

簡介

泛型是一種語言特性,能讓程式碼重複使用。 舉例來說,要計算一個陣列的長度,並不應該取決於它裝的是什麼型別。 這就是為什麼length函式在其型別簽章中使用了泛型型別參數a。

length : List a -> Int

型別中的參數

當一個型別對另一個型別泛型時,我們會用全小寫的名稱來代表那個型別,並稱它為型別參數。 常見的例子有List、Maybe和Result這些自訂型別。

-- Maybe is generic over the type a
type Maybe a
    = Nothing
    | Just a

someString : Maybe String
someString = Just "hello"

someInt : Maybe Int
someInt = Just 42

關於型別參數的名稱,有一點很重要:它們可以有好幾個字元長。 唯一的限制是必須使用全小寫的名稱。 因此,在適當的時候,我們通常會給它們取有描述性的名稱。

一個型別可以對多個其他型別泛型,因此可以有多個型別參數。 這種情況下,每個獨立的型別都會使用不同的全小寫名稱。 彼此獨立並不代表它們不能是同一個型別,只是讓它們有機會可以不同而已。

-- Result is generic over the types error and value
type Result error value
    = Ok value
    | Err error

記錄型別別名也可以有型別參數,雖然比較少見。

-- Event is generic over the type a
type alias Event a =
    { at : Time
    , data : a 
    }

函式中的型別參數

既然型別可以是泛型的,函式當然也可以。 我們可以寫出處理泛型型別的函式,例如Maybe.withDefault。

withDefault : a -> Maybe a -> a
withDefault default maybe =
    case maybe of
      Just value -> value
      Nothing -> default

把其他函式當作參數的函式稱為高階函式,而它們也可以是泛型的。

map : (a -> b) -> Maybe a -> Maybe b
map function maybe =
  case maybe of
    Just value ->
      Just (function value)

    Nothing ->
      Nothing

說明

在這個練習中,你要寫一個泛型(也可以說很神奇!)的 TreasureChest,用來存放寶藏。

1. 定義 TreasureChest 泛型自訂型別

定義一個只有單一變體的TreasureChest自訂型別。

這個變體應該有一個關聯的String值,用來存放寶箱的密碼。

這個變體還應該有一個關聯的泛型值,用來存放寶藏。這個值是泛型的,所以寶藏可以是任何東西。

2. 定義 getTreasure 函式

這個函式應該接受兩個參數

  • 一個String(用來嘗試密碼)
  • 一個TreasureChest泛型自訂型別

這個函式應該拿提供的密碼嘗試與TreasureChest中的String進行比對。

這個函式應該回傳一個Maybe。

如果密碼相符,就回傳Just,並帶上TreasureChest裡的泛型值(也就是寶藏!)

如果密碼不符,就回傳Nothing。

3. 定義 multiplyTreasure 函式

這個(高階)函式應該接受兩個參數

  • 一個倍乘函式,它接受一個泛型參數,並回傳一個相同泛型型別的陣列
  • 一個TreasureChest泛型自訂型別,同樣使用相同的泛型型別

這個函式應該用箱子裡的寶藏來呼叫倍乘函式。

這個函式應該回傳一個新的 TreasureChest,密碼與原本的相同,並帶有倍乘後的寶藏(也就是回傳值)

透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Elm Exercism

準備好開始 寶箱 了嗎?

註冊 Exercism,透過 28 個概念110 個練習 和真人引導來學習並精通 Elm,全部免費。