类型定义中的断言
Assertion in type definition
我有一些类型
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
;;
而且我知道我的代码有问题,如果 p >= q
in B (p, q)
或 A (p, q)
。所以我想在类型上做断言,这样如果我尝试做 A (5, 1)
它会通知我。
是否可以在类型构造函数中进行断言?它应该是什么样子?
我正在努力避免这样的事情:
assert (p < q) ; A(p, q)
因为我在代码中有很多 A 或 B 对象。
没有直接的方法可以将这样的断言放入类型定义本身。
一个好的方法是将您的类型定义为抽象类型(在模块中)并导出用于构造该类型值的函数。这些将是生成该类型值的唯一方法,您可以在函数中包含您喜欢的任何断言。
更新
正如@antron 指出的那样,将类型设为私有而不是抽象可能更适合您的问题。
@Jeffrey Scofield 已经对此给出了完全准确的答案,但这里是请求的示例:
module type MY_TYPE =
sig
type my_type_name = private
| A of (float * float)
| B of (float * float)
| E
val a : float -> float -> my_type_name
val b : float -> float -> my_type_name
val e : my_type_name
end
module My_type : MY_TYPE =
struct
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
let a p q = assert true; A (p, q)
let b p q = assert true; B (p, q)
let e = E
end
let () =
(* My_type.A (1., 2.); *) (* Type error - private type. *)
let x = My_type.a 1. 2. in
(* Can still pattern match. *)
match x with
| My_type.A (_, _) -> ()
| My_type.B (_, _) -> ()
| My_type.E -> ()
签名的主体可以是 .mli
文件,My_type
的主体可以是 .ml
文件。关键是my_type_name
后面跟着MY_TYPE
中的关键字private
。这导致直接使用底部的构造函数被标记为错误,强制所有构造通过函数 a
、b
、e
,您可以在其中包含断言或任意其他表达式。
编辑 为了使函数看起来更像构造函数,您当然可以将它们的参数转换为元组类型。要使模块几乎透明,您可以 open
它在底部。但这些都是品味问题,取决于您。
我有一些类型
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
;;
而且我知道我的代码有问题,如果 p >= q
in B (p, q)
或 A (p, q)
。所以我想在类型上做断言,这样如果我尝试做 A (5, 1)
它会通知我。
是否可以在类型构造函数中进行断言?它应该是什么样子?
我正在努力避免这样的事情:
assert (p < q) ; A(p, q)
因为我在代码中有很多 A 或 B 对象。
没有直接的方法可以将这样的断言放入类型定义本身。
一个好的方法是将您的类型定义为抽象类型(在模块中)并导出用于构造该类型值的函数。这些将是生成该类型值的唯一方法,您可以在函数中包含您喜欢的任何断言。
更新
正如@antron 指出的那样,将类型设为私有而不是抽象可能更适合您的问题。
@Jeffrey Scofield 已经对此给出了完全准确的答案,但这里是请求的示例:
module type MY_TYPE =
sig
type my_type_name = private
| A of (float * float)
| B of (float * float)
| E
val a : float -> float -> my_type_name
val b : float -> float -> my_type_name
val e : my_type_name
end
module My_type : MY_TYPE =
struct
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
let a p q = assert true; A (p, q)
let b p q = assert true; B (p, q)
let e = E
end
let () =
(* My_type.A (1., 2.); *) (* Type error - private type. *)
let x = My_type.a 1. 2. in
(* Can still pattern match. *)
match x with
| My_type.A (_, _) -> ()
| My_type.B (_, _) -> ()
| My_type.E -> ()
签名的主体可以是 .mli
文件,My_type
的主体可以是 .ml
文件。关键是my_type_name
后面跟着MY_TYPE
中的关键字private
。这导致直接使用底部的构造函数被标记为错误,强制所有构造通过函数 a
、b
、e
,您可以在其中包含断言或任意其他表达式。
编辑 为了使函数看起来更像构造函数,您当然可以将它们的参数转换为元组类型。要使模块几乎透明,您可以 open
它在底部。但这些都是品味问题,取决于您。