我有一些类型
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
;;
Run Code Online (Sandbox Code Playgroud)
而且我知道我的代码中存在问题,如果p >= q在B (p, q)或中A (p, q).所以我想在类型中做出断言,这样如果我试着A (5, 1)让它通知我.
是否可以在类型构造函数中进行断言?应该怎么样?
我试图避免这样的事情:
assert (p < q) ; A(p, q)
Run Code Online (Sandbox Code Playgroud)
因为我在代码中有很多A或B对象.
@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 -> ()
Run Code Online (Sandbox Code Playgroud)
签名的主体可以是.mli文件,而主体My_type可以是.ml文件.关键是my_type_name后跟关键字privatein MY_TYPE.这使得底部的直接使用构造函数的被标记为错误,迫使所有建筑都要经过功能a,b,e,在那里你可以包括断言或任意其它表达式.
编辑为了使函数看起来更像构造函数,您当然可以将它们的参数转换为元组类型.要使模块几乎透明,您可以open在底部.但这些都是品味问题,取决于你.
将这样的断言放入类型定义本身并没有直接的方法.
一种好的方法是将类型定义为抽象类型(在模块中),并导出函数以构造类型的值.这些是生成类型值的唯一方法,您可以在函数中包含您喜欢的任何断言.
更新
正如@antron指出的那样,将类型设为私有而非抽象可能更适合您的问题.