用户定义的变量不会识别其自己的类型列表是类型

时间:2017-10-04 23:34:26

标签: recursion types ocaml algebraic-data-types

由于某些原因,我收到错误声称distribute((AndC t),p)cnf而不是cnf list ...除了cnf list是一种类型的cnf。为什么OCaml不会认识到这最终会提供一个列表?

问题点是第11-12行。

type cnf
  = AtomC of signed_atom
  | AndC of cnf list    
  | OrC of cnf * cnf

let rec distribute : cnf * cnf -> cnf = 

  let rec aux = function
    | AndC [], _
    | _, AndC [] -> AndC []
    | AndC (h::t), p -> AndC( distribute(h,p) :: distribute((AndC t),p) )
    | p, AndC (h::t) -> AndC( distribute(p,h) :: distribute(p,(AndC t)) )
    | p, q -> OrC(p, q)
  in aux

1 个答案:

答案 0 :(得分:0)

AndC xxx形式的值不是列表。它是cnf类型的值,包含列表。但它本身并不是一个列表。

像你这样的声明定义了一个新类型cnf,以及三个新的值构造函数AtomCAndCOrC。值构造函数(如名称中所示)用于构造值。它们不是类型。

类型cnf的每个值都将由三个构造函数之一构造。因此,cnf值列表本身不是cnf值。 AndC是必需的。

<强>更新

如果您定义此功能:

let mycons cnf andc =
    match andc with
    | AndC cnfs -> cnf :: cnfs
    | _ -> [cnf] (* Not possible *)

您可以将::替换为mycons,如下所示:

AndC( mycons (distribute (h,p)) (distribute ((AndC t), p)) )

(我没有对此进行测试,但我认为这个想法没问题。声称第二次调用distribute可以保证返回AndC值。)

更新2

您可以直接定义distribute,而不是aux,如下所示:

let rec distribute : cnf * cnf -> cnf = function
| AndC [], _
| _, AndC [] -> AndC []
(* Rewrite these ...
| AndC (h::t), p -> AndC( distribute(h,p) :: distribute((AndC t),p) )
| p, AndC (h::t) -> AndC( distribute(p,h) :: distribute(p,(AndC t)) )
 ... *)
| p, q -> OrC(p, q)