Maybe型別是 Elm 語言用來處理選用值的做法。因此,許多核心 Elm 函式的型別簽章中都會出現它,理解它可說至關重要。Maybe型別的定義如下:
type Maybe a = Nothing | Just a
這在 Elm 的術語中稱為「自訂型別」定義。它表示此型別的值不是Nothing,就是Just某個型別為a的值。建立Maybe值的方式,是使用它的兩個建構子Nothing和Just其中一個。讀取Maybe內容的方式則是模式比對。
matthieu : Maybe String
matthieu = Just "Matthieu"
anon : Maybe String
anon = Nothing
sayHello : Maybe String -> String
sayHello maybeName =
case maybeName of
Nothing -> "Hello, World!"
Just someName -> "Hello, " ++ someName ++ "!"
sayHello matthieu
--> "Hello, Matthieu!"
sayHello anon
--> "Hello, World!"
Maybe模組中還有許多實用的函式,可以用來操作Maybe型別。
sayHelloAgain : Maybe String -> String
sayHelloAgain name = "Hello, " ++ Maybe.withDefault "World" name ++ "!"
capitalizeName : Maybe String -> Maybe String
capitalizeName name = Maybe.map String.toUpper name
capitalizeName matthieu
--> Just "MATTHIEU"
capitalizeName anon
--> Nothing
在這道練習中,你將實作一款角色扮演遊戲的機制。 玩家的角色會以下列的型別表示:
type alias Player =
{ name : Maybe String
, level : Int
, health : Int
, mana : Maybe Int
}
遊戲中的玩家必須達到等級 10,才能解鎖魔力池,進而開始施展法術。 你在這款遊戲中要處理兩項功能:復活機制和施法機制。
撰寫introduce函式的內容。
潛行的玩家可能會隱藏自己的名字,這時會以 "Mighty Magician" 來介紹自己。
否則,就用你自己的名字來介紹自己。
introduce { name = Nothing, level = 2, health = 8, mana = Nothing }
--> "Mighty Magician"
introduce { name = Just "Merlin", level = 2, health = 8, mana = Nothing }
--> "Merlin"
revive函式應該檢查玩家的角色是否確實已經死亡(生命值降到 0)。
如果確實死亡,就回傳一個生命值為 100 的新Player實例。
否則,如果玩家的角色還沒死亡,revive函式會回傳Nothing。
如果玩家的等級是 10 以上,復活時也應該一併回復 100 魔力。
如果玩家的等級低於 10,他們的魔力應該是Nothing。
revive函式應該保留玩家的等級。
deadPlayer = { name = Nothing, level = 2, health = 0, mana = Nothing }
revive deadPlayer
--> Just { name = Nothing, level = 2, health = 100, mana = Nothing }
如果在生命值為 1 以上的玩家身上呼叫revive方法,這個函式應該回傳Nothing。
alivePlayer = { name = Nothing, level = 2, health = 42, mana = Nothing }
revive alivePlayer
--> Nothing
castSpell函式會接受兩個引數:一個Int,表示法術消耗多少魔力,以及一個Player。
它會回傳更新後的玩家,以及這個法術造成的傷害量。
成功施展的法術會造成等同於該法術魔力消耗兩倍的傷害。
不過,如果玩家的魔力不足,什麼都不會發生,玩家維持不變,也不會造成任何傷害。
如果玩家甚至連魔力池都沒有,嘗試施展法術時必須讓玩家的生命值減少等同於該法術魔力消耗的量,而且不會造成任何傷害。
wizard = { name = Nothing, level = 18, health = 123, mana = Just 30 }
( updatedWizard, damage ) = castSpell 14 wizard
updatedWizard.mana --> Just 16
damage --> 28