我正在尝试在ocaml中编写一个函数,该函数将逻辑运算作为参数(如下定义:)
type oper = B of bool
| V of string
| Neg of oper
| And of oper * oper
| Or of oper * oper
| Impl of oper * oper
如果操作可满足则返回“true”(至少在一种情况下返回true),如果不满足则返回“false”(在所有情况下都返回false)。为此,我试图用V true或B false替换V s,直到我得到true并引发Do_it异常。如果我在任何情况下都不成功,我会抛出Not_found异常并评估我在程序结束时得到的异常。
let satisfable operation=
let switch x var tf=
let rec aux1 =function
|B b->B b
|V s when s=var ->aux1 (B tf)
|V s->V s
|And(e1,e2)->(match aux1 e1, aux1 e2 with
|(B false,_)|(_,B false)->B false
|(B true, x)|(x,B true)->aux1 x
|(x1,x2)->And(x1,x2))
|Or(e1,e2)->(match aux1 e1,aux1 e2 with
|(B true, _)|(_,B true)->B true
|(B false, x)|(x,B false)->aux1 x
|(x1,x2)->Or(x1,x2))
|Impl(e1,e2)->(match aux1 e1,aux1 e2 with
|(B false,_)->B false
|(B true,x)->aux1 x
|(x1,x2)->Impl(x1,x2))
|Neg b->(match b with
|B b-> B (not b)
|s->Neg (aux1 s))
in aux1 x
in let rec aux = function
|B b->B b
|V s->(match switch operation s true with
|B true->raise Do_it
|x-> aux (switch operation s true)
)
|V s->(match switch operation s false with
|B true->raise Do_it
|x-> aux (switch operation s false)
)
|V s->raise Not_found
|And(e1,e2)->(match aux e1, aux e2 with
|(B false,_)|(_,B false)->B false
|(B true, x)|(x,B true)->aux x
|(x1,x2)->And(x1,x2))
|Or(e1,e2)->(match aux e1,aux e2 with
|(B true, _)|(_,B true)->B true
|(B false, x)|(x,B false)->aux x
|(x1,x2)->Or(x1,x2))
|Impl(e1,e2)->(match aux e1,aux e2 with
|(B false,_)->B false
|(B true,x)->aux x
|(x1,x2)->Impl(x1,x2))
|Neg b->(match b with
|B b-> B (not b)
|s->Neg (aux s))
in if(try aux operation with Do_it->B true|Not_found->B false)=B false then false else true;;
但它不能按照我想要的方式工作,在某些情况下它甚至会引发Stack溢出异常。
函数“switch”返回一个操作,其中字符串变量“var”已替换为tf(true / false)的值
答案 0 :(得分:2)
您的函数None
正在使用aux
的外部定义,该定义在每次递归调用时都不会更改。
答案 1 :(得分:1)
在函数aux
中,您在V s
上匹配三次。只会分析第一个案例。此外,调用两次switch operation s true
并不是一个好主意,您可以通过声明let case_true = switch operation s true
来避免重复两次相同的计算。