轨道
/
Elm
Elm
/
练习
/
宝箱
宝箱

宝箱

学习练习

简介

泛型

简介

泛型是一种支持代码复用的语言特性。 例如,要计算数组的长度,数组里装的是什么类型并不重要。 正因如此,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,全部免费。