【问题标题】:How to make a data structure which represents a subset of numbers?如何制作表示数字子集的数据结构?
【发布时间】:2019-06-28 19:16:22
【问题描述】:

我想知道是否有办法制作像 Int 类型的东西,它只能表示数字的某个子集(如 0 ~ 29),如果你尝试用它做任何其他事情,编译器会抛出错误.

我知道我可以做类似type MoonPhaseDay = Day1|Day2| ... |Day29 的事情,但这并不能扩展到更大的范围。

我试图牢记“使不可能的状态无法表示”的建议。我可以通过Int 解决问题,但我很好奇是否有更好的方法。

【问题讨论】:

标签: types elm


【解决方案1】:

您正在寻找的东西有时被称为“依赖类型”,并且现在不是 Elm 的一部分。

但是,您可以通过在它自己的模块中创建一个类型来获得类似的东西,而不是导出原始类型构造函数,只导出您提供的自定义函数(使其成为“不透明类型”)。这样,该模块包含唯一需要保护的代码。


This answer by Nathan 在了解 Opaque 类型时可能会有所帮助。

【讨论】:

  • +1 我想补充一点,“不透明类型”,即不导出类型构造函数,而是执行一些约束检查的函数,也称为智能构造函数。这可能有助于进一步搜索该主题。
【解决方案2】:

您需要使用智能构造函数。您通过控制从模块导出的内容来强制执行您的约束。

module Bounded exposing (Bounded, fromInt, toInt)


type Bounded
  = Bounded Int


fromInt : Int -> Maybe Bounded
fromInt n =
  if n < 0 || n > 29 then
    Nothing
  else
    Just (Bounded n)


toInt : Bounded -> Int
toInt (Bounded n) = n

说明

Bounded 类型被定义为具有一个数据构造函数的联合类型。导出类型时,我们不导出构造函数,即它不是公共 API 的一部分。这称为不透明类型

模块的用户只能使用fromInt 创建Bounded 类型。 fromInt 被称为智能构造函数,因为它有一些逻辑(智能)来执行约束。

如果您需要使用它包裹的整数,请使用toInttoInt 保证总是返回一个介于 0 和 29 之间的整数。不存在允许包装任何其他整数的隐藏后门。

HaskellWiki 在smart constructors 上有一篇不错的文章。

最后,Richard Feldman 在他的演讲“The Gilded Rose 的类型和测试”中介绍了一个很好的例子 here,它准确地解释了你想要做什么。

【讨论】:

    猜你喜欢
    • 2012-10-09
    • 2022-07-21
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 2011-08-26
    • 2011-04-24
    相关资源
    最近更新 更多