我想知道是否有一种方法可以制作类似Int
类型的内容,该类型只能表示数字的某个子集(例如0〜29),并且如果您尝试执行其他操作,则使编译器抛出错误用它。
我知道我可以做类似type MoonPhaseDay = Day1|Day2| ... |Day29
的事情,但这并不能扩大范围。
我试图牢记“使不可能的状态无法代表”的建议。我可以通过Int
来解决,但是我很好奇是否有更好的方法。
答案 0 :(得分:2)
您正在寻找的东西有时被称为“从属类型”,并且今天不属于Elm。
但是,通过在其自己的模块中创建一个类型,而不是导出原始类型构造函数,而仅导出您提供的自定义函数(使其成为“不透明类型”),您可以获得类似的结果。这样,该模块包含了唯一需要保护的代码。
This answer by Nathan在了解不透明类型时可能会有所帮助。
答案 1 :(得分:0)
您需要使用智能构造函数。您可以通过控制从模块导出的内容来强制执行约束。
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的一部分。这称为不透明类型。
该模块的用户只能使用Bounded
创建fromInt
类型。 fromInt
被称为智能构造函数,因为它具有一些逻辑(智能)来执行约束。
如果需要使用整数进行换行,请使用toInt
。保证toInt
总是返回0到29之间的一个整数。没有隐藏的后门可以包装任何其他整数。
HaskellWiki在smart constructors上写得很好。
最后,理查德·费尔德曼(Richard Feldman)在他的演讲“镀金玫瑰的类型和测试”中,通过一个不错的示例here来解释了您想要做什么。