OCaml 有没有办法在记录中声明一个整数,它是一些整数的区间?
Is there a way in OCaml to declare in a record an integer which is an interval of some integers?
我被困在这个问题上,我不得不:
将类型日期定义为三元组,其中第一个组件是表示为
整数,第二个分量是区间 [1..12] 中的整数
代表月份,最后一个组成部分代表一天,有一个整数
数.
type date = { year: int; month: int; day:int};;
{year = 2012; month = 12; day = 21};;
这很好用,但对于参数月,我需要输入 1 到 12 之间的整数。
如果你只想为几个月使用一个变体并枚举整个月。你可以对天数做同样的事情,但我会避免它。
如果你想要一个更一般的概念,比如范围类型:你不想要那个,因为月份有 30 天或 31 天,而二月有 28-29 天,具体取决于闰年,所以它是依赖范围......如果这张支票可用,那么你想要哪个范围?您需要的检查非常具体:例如,我只在带有扩展名的 cpp 中看到过这个,并且您被迫在范围内使用 int (非常无用)。因为这个扩展需要 static int 你不能真正用于日期。 OCaml 无法做到这一点,因为所有 int 都是 int
而不是 30 或 31。通常的解决方法是创建一个函数,该函数采用三个 int 验证它们是否在有效范围内并且 return date option
并从外部将其设为私有,这样您就不会破坏不变量。我们称之为智能构造函数。
module SafeDate : sig
type date = private { year: int; month: int; day:int}
val create: int -> int -> int -> date option
end = struct
type date = { year: int; month: int; day:int}
let create year month day = if (* put formula/code to say if correct *) then Some{year; month; day} else None
end
没有,但是可以防止意外发生。
OCaml(和其他地方)中的时间和日期库通常确保日期对象的组件落在正确的范围内,而无需特殊的类型系统技巧。
在 OCaml 中,一个好的解决方案可能是将日期字段公开为只读。这意味着模块的用户将无法使用符号 {year=...; month=...; day=...}
创建此类记录。这是通过提供一个明确的模块接口(.mli 文件)来实现的,该接口将日期类型声明为 private
:
(* Date.mli *)
type t = private {
year: int;
month: int;
day: int;
}
(** Create a date object if and only if given acceptable values *)
val create : year:int -> month:int -> day:int -> t option
实施(Date.ml
文件)与往常一样。特别是,类型定义中没有 private
关键字:
(* Date.ml *)
type t = {
year: int;
month: int;
day: int;
}
let create ...
您也可以借此发挥创意。例如,您可以让库安全地公开从 year/month/day 派生的字段,例如自年初以来的天数等
我被困在这个问题上,我不得不: 将类型日期定义为三元组,其中第一个组件是表示为 整数,第二个分量是区间 [1..12] 中的整数 代表月份,最后一个组成部分代表一天,有一个整数 数.
type date = { year: int; month: int; day:int};;
{year = 2012; month = 12; day = 21};;
这很好用,但对于参数月,我需要输入 1 到 12 之间的整数。
如果你只想为几个月使用一个变体并枚举整个月。你可以对天数做同样的事情,但我会避免它。
如果你想要一个更一般的概念,比如范围类型:你不想要那个,因为月份有 30 天或 31 天,而二月有 28-29 天,具体取决于闰年,所以它是依赖范围......如果这张支票可用,那么你想要哪个范围?您需要的检查非常具体:例如,我只在带有扩展名的 cpp 中看到过这个,并且您被迫在范围内使用 int (非常无用)。因为这个扩展需要 static int 你不能真正用于日期。 OCaml 无法做到这一点,因为所有 int 都是 int
而不是 30 或 31。通常的解决方法是创建一个函数,该函数采用三个 int 验证它们是否在有效范围内并且 return date option
并从外部将其设为私有,这样您就不会破坏不变量。我们称之为智能构造函数。
module SafeDate : sig
type date = private { year: int; month: int; day:int}
val create: int -> int -> int -> date option
end = struct
type date = { year: int; month: int; day:int}
let create year month day = if (* put formula/code to say if correct *) then Some{year; month; day} else None
end
没有,但是可以防止意外发生。
OCaml(和其他地方)中的时间和日期库通常确保日期对象的组件落在正确的范围内,而无需特殊的类型系统技巧。
在 OCaml 中,一个好的解决方案可能是将日期字段公开为只读。这意味着模块的用户将无法使用符号 {year=...; month=...; day=...}
创建此类记录。这是通过提供一个明确的模块接口(.mli 文件)来实现的,该接口将日期类型声明为 private
:
(* Date.mli *)
type t = private {
year: int;
month: int;
day: int;
}
(** Create a date object if and only if given acceptable values *)
val create : year:int -> month:int -> day:int -> t option
实施(Date.ml
文件)与往常一样。特别是,类型定义中没有 private
关键字:
(* Date.ml *)
type t = {
year: int;
month: int;
day: int;
}
let create ...
您也可以借此发挥创意。例如,您可以让库安全地公开从 year/month/day 派生的字段,例如自年初以来的天数等