在 Gleam 中,自定义类型用来定义新的数据类型。一个自定义类型可以有多个_变体_,每个变体都有自己的名字。
pub type Season {
Spring
Summer
Autumn
Winter
}
自定义类型的每个变体都可以选择性地携带一些数据,而且不同变体携带的数据类型可以不同。当变体携带数据时,它就被称为_记录_。
pub type Number {
SomeInt(Int)
SomeFloat(Float)
Invalid
}
如果要为某个变体创建值,当它不包含额外数据时(Spring),直接引用它的名字即可;当它包含额外数据时(SomeInt(2)),则把它当作函数来调用。
let spring = Spring
let integerTwo = SomeInt(2)
自定义类型和 Gleam 中的其他所有东西一样,都具有_结构相等性_:也就是说,两个值只要属于同一个变体、携带的数据相同,就彼此等价。
Spring == Spring // -> True
Spring == Autumn // -> False
SomeInt(2) == SomeInt(2) // -> True
SomeInt(2) == SomeFloat(2.0) // -> False
使用 case 表达式,可以对自定义类型的变体进行模式匹配。
import gleam/int
import gleam/float
pub fn describe(flexible_number: Number) -> String {
case flexible_number {
SomeFloat(f) -> "Float: " <> float.to_string(f)
SomeInt(i) -> "Int: " <> int.to_string(i)
Invalid -> "Neither a float nor an int"
}
}
在这个练习里,今天是情人节,你和伴侣打算一起做点开心的事。你的伴侣有很多想法,现在请你给这些想法打分,好挑出要进行的活动。
你的伴侣提出了以下想法:
你有六项任务,帮你选出情人节的活动。
对于伴侣提出的每个想法,你都要用三个选项之一来回应:yes、no 或 maybe。
定义Approval自定义类型,用以下三个构造子表示这些选项:Yes、No和Maybe。
你的伴侣选了两家可能去的餐厅:一家是韩式料理,另一家是土耳其料理。
定义Cuisine自定义类型,用以下两个构造子表示这两种料理:Korean和Turkish。
可选的电影非常多,为了缩小范围,你的伴侣还列出了电影的类型。
定义Genre自定义类型,用构造子表示以下类型:Crime、Horror、Romance和Thriller。
如前所述,你的伴侣想出了五种不同的活动:玩桌游、放松一下、看电影、去餐厅和散步。
定义Activity自定义类型来表示这些活动:
BoardGame:没有关联数据。Chill:没有关联数据。Movie:以它的Genre作为关联数据。Restaurant:以它的Cuisine作为关联数据。Walk:以Int作为关联数据,表示要步行的公里数。最后,你可以给伴侣的想法评分了。你对伴侣想法的态度如下:
实现一个名为rate_activity的函数,它接收一个Activity值,并根据上面的态度返回Approval:
rate_activity(Restaurant(Turkish))
// -> Maybe