Types 如何将OCaml整数类型约束为整数范围?
在阅读真实世界的OCaml书籍时,我遇到了以下类型声明(第6章:变体): 我认为RGB和灰色变体可以进一步限制。例如,RGB元组中的每个int只能具有0-5的值 在Erlang中,我会这样做:Types 如何将OCaml整数类型约束为整数范围?,types,ocaml,Types,Ocaml,在阅读真实世界的OCaml书籍时,我遇到了以下类型声明(第6章:变体): 我认为RGB和灰色变体可以进一步限制。例如,RGB元组中的每个int只能具有0-5的值 在Erlang中,我会这样做: -type rgbint() :: 0 | 1 | 2 | 3 | 4 | 5. -type rgb() :: {rgb_int(), rgb_int(), rgb_int(). 然而,当我在OCaml(utop)中尝试此功能时,它抱怨: # type rgbint = 0 | 1 | 2 | 3 |
-type rgbint() :: 0 | 1 | 2 | 3 | 4 | 5.
-type rgb() :: {rgb_int(), rgb_int(), rgb_int().
然而,当我在OCaml(utop)中尝试此功能时,它抱怨:
# type rgbint = 0 | 1 | 2 | 3 | 4 | 5 ;;
Error: Parse error: [type_kind] expected after "=" (in [opt_eq_pluseq_ctyp])
问题:
- 在OCaml中,是否不允许在类型定义的RHS上使用文本
- 在OCaml中,如何执行上面的Erlang rgbint()定义
Ivan通过某个基本类型的值列表来定义类型是有意义的,但是OCaml没有这样的类型。它有一组基本类型,如
int
和char
。您可以定义自己的新基元类型,其值为文本,如Yes
和No
。(当您定义这样一个文字时,它看起来像一个大写的标识符。)您可以将这些文字与参数化类型(如列表、数组等)相结合
如果确实希望int值限制在某个范围内,可以将其定义为模块接口隐藏的抽象类型。在该模块中,您需要定义要在有限的整数范围内支持的所有操作。(请注意,在通常的算术运算中,此类类型不是闭合的。)
您还可以定义:
type rgbint = RBG0 | RGB1 | RGB2 | RGB3 | RGB4 | RGB5
实际上,这可能是您最终要做的事情,尽管当您将底层值视为数字时,这种类型会感觉很麻烦。这是私有类型的典型用例
OCaml允许您
这使得它介于具体类型和抽象类型之间:
- 与具体类型的值类似,私有类型的值 可以使用am匹配模式解构
- 与抽象类型的值一样,私有类型的值 只能使用模块中的函数构造 定义此类型
module Color : sig
type t =
| Basic of basic_color * weight (* basic colors, regular and bold *)
| RGB of rgbint * rgbint * rgbint (* 6x6x6 color cube *)
| Gray of int (* 24 grayscale levels *)
and basic_color =
| Black | Red | Green | Yellow | Blue | Magenta | Cyan | White
and weight = Regular | Bold
and rgbint = private int
val rgb : int * int * int -> t
end = struct
type t =
| Basic of basic_color * weight
| RGB of rgbint * rgbint * rgbint
| Gray of int
and basic_color =
| Black | Red | Green | Yellow | Blue | Magenta | Cyan | White
and weight = Regular | Bold
and rgbint = int
let rgb (r, g, b) =
let validate x =
if x >= 0 && x < 6 then x else invalid_arg "Color.rgb"
in
RGB (validate r, validate g, validate b)
end
无法从其组件中自组装Color.RGB
值:
# Color.RGB(0,0,0);;
Characters 10-11:
Color.RGB(0,0,0);;
^
Error: This expression has type int but an expression was expected of type
Color.rgbint
可以使用类型强制将Color.rgbint
类型的值解构为整数:
# match Color.rgb(0,0,0) with
| Color.RGB(r,g,b) ->
if ((r,g,b) :> int * int * int) = (0, 0, 0) then
"Black"
else
"Other"
| _ -> "Other";;
- : string = "Black"
Yaron Minsky写了两篇关于私人类型的博文,值得一读:
# Color.RGB(0,0,0);;
Characters 10-11:
Color.RGB(0,0,0);;
^
Error: This expression has type int but an expression was expected of type
Color.rgbint
# match Color.rgb(0,0,0) with
| Color.RGB(r,g,b) ->
if ((r,g,b) :> int * int * int) = (0, 0, 0) then
"Black"
else
"Other"
| _ -> "Other";;
- : string = "Black"