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