SHI1485
SHI1485

Reputation: 121

Use variant from dependency

I have this code:

cnf.mli

type literal
type clause
type cnf
type l_diff

val l_compare: literal -> literal -> l_diff

cnf.ml (partial)

type l_diff = Same | Negation | Different

checker.ml (partial)

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

This works in utop using:

#mod_use "cnf.ml";;
#use "checker.ml";;

But if I try to compile checker I get the following error:

compile command:

ocamlbuild cnf.cma
ocamlbuild checker.cma

error:

+ /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.

Am I using a variant the wrong way, or using the compiler incorrectly?

Upvotes: 0

Views: 84

Answers (1)

octachron
octachron

Reputation: 18892

Neither, you are using abstract types in signature in the wrong way. When you write in cnf.mli

type l_diff

this declares the type l_diff as an abstract type, in other words a black box whose content is hidden.

Contrarily, when using #mod_use "cnf.ml" the toplevel infers a signature by itself and makes all type declarations transparent:

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

val l_compare: literal -> literal -> l_diff

(If you want to see the full inferred signature ocamlbuild cnf.inferred.mli should work.) With this signature, the constructor of l_diff are visible and it becomes possible to construct directly or pattern match values of type l_diff.

More generally, your signature cnf.mli is far too restrictive: With this signature, the only way to create a value of type l_diff is to call l_compare. However it would be then impossible to observe the content of the type. Similarly, with the interface cnf.mli that you provided, it is impossible to create a value of type literal.

Upvotes: 5

Related Questions