当试图编写一个解决玩具SAT问题的简单程序时,我遇到了以下问题,我无法理解。
我有一个类型变量,其定义如下:
type prefix =
| Not
| None
type variable =
| Fixed of (prefix * bool)
| Free of (prefix * string)
我可以从中构建类型变量列表的子句和类型子句列表的公式。从本质上讲,这归结为有一个公式 无论是CNF还是DNF(这与问题关系不大)。 现在尝试简化一个条款时,我会执行以下操作:
现在我有一个只包含固定变量的列表,我现在想通过这样的方式将它组合成一个固定值
let combine l =
match l with
| [] -> []
| [x] -> [x]
| (* Get the first two variables, OR/AND them
and recurse on the rest of the list *)
我如何在功能语言中实现我想要的行为?我在OCaml的经历并不是那么大,我是一个初学者。 我试过做x :: xs :: rest - > x< ||> xs< ||>结合休息,但这不起作用。其中< ||>只是OR变量的自定义运算符。
感谢您的帮助。
答案 0 :(得分:2)
如何使用已经存在的高阶高阶函数?
let combine = function
| x::xs -> List.fold_left (<||>) x xs
| [] -> failwith "darn, what do I do if the list is empty?"
澄清:
List.fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
获取一个获取运行聚合的函数和列表的下一个元素;它返回新聚合;然后我们需要一个初始值和要折叠的项目列表。
在括号中使用中缀运算符<||>
使其成为前缀函数,因此我们可以将其赋予List.fold_left
- 而不是写(fun a b -> a <||> b)
。
如果您的<||>
运算符中有一个中性元素,我们可以将其称为one
,我们可以更简洁地编写它:
let combine = List.fold_left (<||>) one
由于List.fold_left
需要三个参数,我们只给它两个,combine
这里是variable list -> variable
的函数,就像前一个一样。如果您想知道为什么会这样,请查看 currying 的概念。
答案 1 :(得分:1)
这是我的尝试:
let rec combine l =
match l with
| [] -> []
| [x] -> [x]
| a :: b :: rest -> combine ((a <||> b) :: rest)
请注意,您需要let rec
。