轨道
/
Gleam
Gleam
/
练习
/
安全宝箱
安全宝箱

安全宝箱

学习练习

简介

不透明类型

Gleam 中的不透明类型是一种自定义类型,只有定义该类型的模块才能构造或模式匹配该类型的值。这有助于创建只能以特定方式使用的类型。

不透明类型使用opaque关键字定义。

pub opaque type PositiveInt {
  PositiveInt(inner: Int)
}

这个PositiveInt类型适用于需要整数、但该整数必须大于等于零的场合。普通的 GleamInt不能这样用,因为它们也可以是负数。

定义该类型的模块可以定义一个函数来获取内部的 int 值,以及一个用于创建PositiveInt类型的函数,如果值不是正数,该函数会返回一个错误。

pub fn from_int(i: Int) -> Result(PositiveInt, String) {
  case i {
    _ if i < 0 -> Error("Value must be positive")
    _ -> Ok(PositiveInt(i))
  }
}

pub fn to_int(i: PositiveInt) -> Int {
  i.inner
}

有了这个 API,其他模块无法用负值构造PositiveInt,因此任何接受PositiveInt的函数都可以确定该值是正数。

说明

眼尖的同学可能已经注意到,上一个练习里的TreasureChest类型并不怎么安全!

如果你用过get_treasure函数,就必须提供密码,但你仍然可以解构TreasureChest类型,在不知道密码的情况下拿到宝藏。

我们用不透明类型来解决这个问题吧。

1. 定义不透明类型TreasureChest。

TreasureChest包含两个字段:

  • 密码,类型为String。
  • 宝藏,类型为泛型。

TreasureChest类型必须是不透明类型。

2. 定义create函数。

这个函数接受两个实参:

  • 一个String类型的密码。
  • 一个任意类型的宝藏值。

函数返回一个TreasureChest,其中包含密码和这个值。

如果密码短于 8 个字符,函数应返回一个错误,提示Password must be at least 8 characters long。

3. 定义open函数。

这个函数接受两个实参:

  • 一个TreasureChest。
  • 一个String类型的密码。

如果密码与TreasureChest中的密码一致,函数就应返回宝藏,否则应返回一个错误,提示Incorrect password。

通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Gleam Exercism

准备好开始 安全宝箱 了吗?

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