gpt4 book ai didi

types - 如何将 OCaml 整数类型限制为整数范围?

转载 作者:行者123 更新时间:2023-12-01 07:36:09 26 4
gpt4 key购买 nike

阅读 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

我认为可以进一步限制 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 | 4 | 5 ;;

Error: Parse error: [type_kind] expected after "=" (in [opt_eq_pluseq_ctyp])

问题:

  • 在 OCaml 中,不允许在类型定义的 RHS 上使用字面量吗?
  • 如何在 OCaml 中执行类似上述 Erlang rgbint() 定义的操作?

感谢和祝福

伊万

最佳答案

这是私有(private)类型的典型用例

OCaml 允许您 mark a type as private in a signature这使它介于具体和抽象类型之间:

  • 类似于具体类型的值,私有(private)类型的值可以使用 am 匹配模式解构;

  • 类似于抽象类型的值,私有(private)类型的值只能使用模块中的函数构造定义这种类型。

例如,您的代码片段可以翻译为

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 值:

# Color.rgb(0,0,0);;
- : Color.t = Color.RGB (0, 0, 0)

不可能从其组件中自组装 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 写了两篇关于私有(private)类型的博文,值得一读:

关于types - 如何将 OCaml 整数类型限制为整数范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35107944/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com