OCaml错误中的逻辑操作

OCaml错误中的逻辑操作,ocaml,Ocaml,我试图用OCaml编写一个函数来解决逻辑运算。这一尝试是成功的: let rec tf =function |B b->b |V s->failwith "not good" |And(e1,e2)->tf e1&&tf e2 |Or(e1,e2)->tf e1||tf e2 |Neg b-> not (tf b);; 但当我编写以下函数时,程序会警告我一些错误: type bv = B of bool | V of strin

我试图用OCaml编写一个函数来解决逻辑运算。这一尝试是成功的:

let rec tf =function
  |B b->b
  |V s->failwith "not good"
  |And(e1,e2)->tf e1&&tf e2
  |Or(e1,e2)->tf e1||tf e2
  |Neg b-> not (tf b);;
但当我编写以下函数时,程序会警告我一些错误:

type bv = B of bool | V of string | Neg of bv
             | And of bv * bv | Or of bv * bv;;
module MS=Map.Make(String);;

let  prop x map=
  let rec aux=function
  |B b->b
  |Neg b-> not (aux b)
  |V s->try aux(B (MS.find s map)) with Not_found->failwith ""
  |And(e1,e2)->aux e1&&aux e2
  |Or(e1,e2)->aux e1||aux e2
  in aux x;;          

    Characters 145-148:
    |And(e1,e2)->aux e1&&aux e2
     ^^^
Error: This variant pattern is expected to have type exn
       The constructor And does not belong to type exn
其中map是(string*bool)map。如果函数的参数“x”是一个字符串,那么它将在映射中查找它并获得布尔值,然后在进一步的演算中使用它。如果找不到x,它将抛出异常并结束函数。
我知道这与VS匹配有关,但我不知道这里出了什么问题

让我展示一下,知道OCaml语法的压头是如何缩进代码的:

let prop x map=
  let rec aux=function
    |B b->b
    |Neg b-> not (aux b)
    |V s->try aux(B (MS.find s map)) with Not_found->failwith ""
                                        | And(e1,e2)->aux e1&&aux e2
                                        | Or(e1,e2)->aux e1||aux e2
  in aux x;;
现在,很明显,为什么
被认为是例外

您可以将呼叫插入aux,例如

let prop x map =
  let rec aux=function
    |B b->b
    |Neg b-> not (aux b)
    |V s-> (try aux(B (MS.find s map)) with Not_found->failwith "")
    |And(e1,e2)->aux e1&&aux e2
    |Or(e1,e2)->aux e1||aux e2
  in aux x;;
但是,在每个递归调用周围安装异常处理程序并不是一个好主意,因为这会导致在堆栈上安装
N
异常记录,从而破坏尾部递归的思想。最好按照以下方式重写算法:

 let prop x map=
  let rec aux=function
    |B b->b
    |Neg b-> not (aux b)
    |V s when MS.mem s map -> aux (B (MS.find s map))
    |V s -> invalid_arg ("Unbound variable: " ^ s)
    |And(e1,e2) -> aux e1&&aux e2
    |Or(e1,e2) -> aux e1||aux e2 in
  aux x

让我演示一下,了解OCaml语法的压头将如何缩进代码:

let prop x map=
  let rec aux=function
    |B b->b
    |Neg b-> not (aux b)
    |V s->try aux(B (MS.find s map)) with Not_found->failwith ""
                                        | And(e1,e2)->aux e1&&aux e2
                                        | Or(e1,e2)->aux e1||aux e2
  in aux x;;
现在,很明显,为什么
被认为是例外

您可以将呼叫插入aux,例如

let prop x map =
  let rec aux=function
    |B b->b
    |Neg b-> not (aux b)
    |V s-> (try aux(B (MS.find s map)) with Not_found->failwith "")
    |And(e1,e2)->aux e1&&aux e2
    |Or(e1,e2)->aux e1||aux e2
  in aux x;;
但是,在每个递归调用周围安装异常处理程序并不是一个好主意,因为这会导致在堆栈上安装
N
异常记录,从而破坏尾部递归的思想。最好按照以下方式重写算法:

 let prop x map=
  let rec aux=function
    |B b->b
    |Neg b-> not (aux b)
    |V s when MS.mem s map -> aux (B (MS.find s map))
    |V s -> invalid_arg ("Unbound variable: " ^ s)
    |And(e1,e2) -> aux e1&&aux e2
    |Or(e1,e2) -> aux e1||aux e2 in
  aux x