在阅读《 Real World OCaml》一书时,我遇到了以下类型声明(第6章:变体):
# type color =
| Basic of basic_color * weight (* basic colors, regular and bold *)
| RGB of int * int * int (* 6x6x6 color cube *)
| Gray of int (* 24 grayscale levels *)
;;
type color =
Basic of basic_color * weight
| RGB of int * int * int
| Gray of int
Run Code Online (Sandbox Code Playgroud)
我认为可以进一步限制RGB和Gray变体。例如,RGB元组中的每个int只能具有值0-5。
在Erlang中,我会这样做:
-type rgbint() :: 0 | 1 | 2 | 3 | 4 | 5.
-type rgb() :: {rgb_int(), rgb_int(), rgb_int().
Run Code Online (Sandbox Code Playgroud)
但是,当我在OCaml(在utop中)尝试此操作时,它抱怨:
# type rgbint = 0 | 1 | 2 | 3 | 4 | 5 ;;
Error: Parse error: [type_kind] expected after "=" (in [opt_eq_pluseq_ctyp])
Run Code Online (Sandbox Code Playgroud)
问题:
衷心的祝福
伊万
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
Run Code Online (Sandbox Code Playgroud)
使用此定义,我们当然可以Color.RGB使用以下Color.rgb函数创建值:
# Color.rgb(0,0,0);;
- : Color.t = Color.RGB (0, 0, 0)
Run Code Online (Sandbox Code Playgroud)
不能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
Run Code Online (Sandbox Code Playgroud)
可以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"
Run Code Online (Sandbox Code Playgroud)
Yaron Minsky写了两篇有关私有类型的博客文章,值得一读:
| 归档时间: |
|
| 查看次数: |
582 次 |
| 最近记录: |