使用依赖的变体

SHI*_*485 0 ocaml

我有这个代码:

cnf.mli

type literal
type clause
type cnf
type l_diff

val l_compare: literal -> literal -> l_diff
Run Code Online (Sandbox Code Playgroud)

cnf.ml(部分)

type l_diff = Same | Negation | Different
Run Code Online (Sandbox Code Playgroud)

checker.ml(部分)

open Cnf
type solution = (literal * bool) list

let rec solve_literal sol l =
    match sol with
    | [] -> false
    | (hl, b)::rs when (l_compare l hl) = Same -> b
    | (hl, b)::rs when (l_compare l hl) = Negation -> not b
    | _::rs -> solve_literal rs l
Run Code Online (Sandbox Code Playgroud)

这适用于utop使用:

#mod_use "cnf.ml";;
#use "checker.ml";;
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试编译,checker我会收到以下错误:

编译命令:

ocamlbuild cnf.cma
ocamlbuild checker.cma
Run Code Online (Sandbox Code Playgroud)

错误:

+ /home/user/.opam/4.05.0/bin/ocamlc.opt -c -o checker.cmo checker.ml
File "checker.ml", line 7, characters 42-46:
Error: Unbound constructor Same
Hint: Did you mean Some?
Command exited with code 2.
Compilation unsuccessful after building 6 targets (2 cached) in 00:00:00.
Run Code Online (Sandbox Code Playgroud)

我是否以错误的方式使用变体,或者使用编译器错误?

oct*_*ron 5

你也没有以错误的方式在签名中使用抽象类型.当你写作cnf.mli

type l_diff
Run Code Online (Sandbox Code Playgroud)

这将类型声明l_diff为抽象类型,换句话说是一个隐藏内容的黑盒子.

相反,当使用#mod_use "cnf.ml"toplevel本身推断签名并使所有类型声明透明时:

type literal = …
type clause = …
type cnf = …
type l_diff = Same | Negation | Different

val l_compare: literal -> literal -> l_diff
Run Code Online (Sandbox Code Playgroud)

(如果要查看完整的推断签名ocamlbuild cnf.inferred.mli应该有效.)使用此签名,构造函数l_diff是可见的,可以直接构造类型的模式匹配值l_diff.

更一般地说,您的签名cnf.mli过于严格:使用此签名,创建类型值的唯一方法l_diff是调用l_compare.然而,然后不可能观察到该类型的内容.同样,使用cnf.mli您提供的接口,无法创建类型的值literal.