Ocaml将布尔列表评估为单个布尔值

时间:2015-10-07 20:47:15

标签: list pattern-matching ocaml

当试图编写一个解决玩具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变量的自定义运算符。

感谢您的帮助。

2 个答案:

答案 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