由于某些原因,我收到错误声称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
答案 0 :(得分:0)
AndC xxx
形式的值不是列表。它是cnf
类型的值,包含列表。但它本身并不是一个列表。
像你这样的声明定义了一个新类型cnf
,以及三个新的值构造函数,AtomC
,AndC
,OrC
。值构造函数(如名称中所示)用于构造值。它们不是类型。
类型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)