类型定义中的断言

时间:2015-11-02 16:37:41

标签: ocaml assert

我有一些类型

type my_type_name =
    | A of (float * float)
    | B of (float * float)
    | E
;;

我知道我的代码中存在问题,p >= qB (p, q)A (p, q)。所以我想在类型中做出断言,这样如果我试图制作A (5, 1)它会通知我。

是否可以在类型构造函数中进行断言?它应该是什么样的?

我试图避免这样的事情:

assert (p < q) ; A(p, q)

因为我在代码中有很多A或B对象。

2 个答案:

答案 0 :(得分:7)

@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后跟private中的关键字MY_TYPE。这会导致底部的构造函数的直接使用被标记为错误,迫使所有构造都通过函数abe,您可以在其中包含断言或任意其他表达。

编辑为了使函数看起来更像构造函数,您当然可以将它们的参数转换为元组类型。要使模块几乎透明,您可以在底部open。但这些都是品味问题,取决于你。

答案 1 :(得分:5)

没有直接的方法将这样的断言放入类型定义本身。

一种好方法是将类型定义为抽象类型(在模块中),并导出函数以构造类型的值。这些是生成类型值的唯一方法,您可以在函数中包含您喜欢的任何断言。

<强>更新

正如@antron指出的那样,将类型设为私有而非抽象可能更适合您的问题。