OCaml错误中的逻辑操作

时间:2016-11-01 21:26:13

标签: 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 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)地图。如果函数的参数“x”是一个字符串,那么它将在map中查找并获取布尔值,然后在进一步的微积分中使用它。如果找不到x,它会抛出异常并结束该函数。 我知道它与V s匹配有关但我不知道这里有什么问题

1 个答案:

答案 0 :(得分:4)

让我说明一下,知道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;;

现在,很明显,为什么AndOr应该是例外。

您可以将您的呼叫括号括起来,例如,

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