轨道
/
Elm
Elm
/
练习
/
情人节
情人节

情人节

学习练习

简介

自定义类型

Elm 中的自定义类型表示一组固定数量的具名情况。每个值都恰好对应其中一种具名情况。

自定义类型使用type关键字定义,需要的语法非常少。它是 Elm 编程中最重要的技术之一,用来让代码中可能出现的值与现实世界中合法的值完全吻合,从而不给无效数据留下任何空间,也让不可能的状态无法在代码中表示。

type Season
    = Spring
    | Summer
    | Autumn
    | Winter

自定义类型的每个情况都可以关联数据,也可以不关联;不同的情况可以关联不同类型的数据。如果所有情况都没有关联数据,这种可辨识联合就类似于其他语言通常所说的_枚举_(或 enum)。

type FlexibleNumber
    = Integer Int
    | Float Float
    | Invalid

为特定的情况创建值,可以直接引用它的名字(Spring),前提是该类型定义在同一个模块中,或者已通过import SeasonModule exposing (Season(..))这种语法导入;也可以通过它的完全限定名(Season.Spring)来引用,前提是已通过import SeasonModule exposing (Season)这种语法导入。

integerTwo = Integer 2
invalid = FlexibleNumber.Invalid

自定义类型和 Elm 中的其他一切一样,都具有_结构相等性_,也就是说,同一个情况、且(可选的)数据也相同的两个值是等价的。

处理自定义类型的首选方式是模式匹配:

let describe flexibleNumber =
    case flexibleNumber of
        Integer i ->
            "Integer: " ++ fromInt(i)

        Float f ->
            "Float: " ++ fromFloat(f)

        Invalid   ->
            "Invalid"

说明

在这个练习中,今天是情人节,你和你的伴侣打算一起做点开心的事。你的伴侣有很多想法,现在请你给这些想法打分,好挑出要参加的活动。

你的伴侣提出了以下想法:

  • 玩桌游
  • 放松一下
  • 看场电影
  • 去餐厅吃饭

你有 6 个任务,帮助你选出情人节的活动。

1. 定义 Approval

对于伴侣提出的每个想法,你用 3 个选项之一来回应:是、否或也许。

定义Approval自定义类型,用以下 3 种情况表示这些选项:Yes、No 和 Maybe。

2. 定义 Cuisine

你的伴侣挑出了 2 家可能的餐厅:一家做韩国料理,另一家做土耳其料理。

定义Cuisine自定义类型,用以下 2 种情况表示这些菜系:Korean 和 Turkish。

3. 定义 Genre

可供选择的电影非常多,为了缩小范围,你的伴侣还列出了电影的题材。

定义Genre自定义类型,用以下情况表示这些题材:Crime、Horror、Romance 和 Thriller。

4. 定义 Activity

如前所述,你的伴侣想出了 5 种不同的活动:玩桌游、放松一下、看场电影和去餐厅吃饭。

定义Activity自定义类型来表示这些活动类型:

  • BoardGame:没有关联数据。
  • Chill:没有关联数据。
  • Movie:带有Genre作为关联数据。
  • Restaurant:带有Cuisine作为关联数据。

5. 给活动打分

最后,你可以给伴侣的想法打分了。你对伴侣想法的感觉是这样的:

  • 玩桌游:不可以。
  • 放松一下:不可以。
  • 看场电影:如果是浪漫电影,就可以;否则,不可以。
  • 去餐厅吃饭:如果是韩国料理,就可以;如果是土耳其料理,也许可以。

实现一个名为rateActivity的函数,它接收一个Activity值,并根据上面的想法返回对应的Approval:

rateActivity (Restaurant Turkish)
-- => Maybe
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Elm Exercism

准备好开始 情人节 了吗?

注册 Exercism,借助 28 个概念110 个练习 和真人导师指导,学习并掌握 Elm,全部免费。