OCaml:列表中的元素组合,功能推理

时间:2016-08-25 17:04:05

标签: list functional-programming ocaml automata

我回到OCaml编码,我错过了很多。我错过了这么多,我完全失去了这种语言的推理,今天我就碰壁了。

我想要做的是在一组n个列表之间组合元素。 我首先尝试在两个任意大小的列表之间组合元素来分解问题。

假设我们必须列出:-l1 = [1;2;3]

我想要做的是获得以下列表:

l2 = [10,20]

我知道如何使用循环结构来做到这一点,但我真的想在没有它们的情况下解决这个问题。

我尝试了以下内容:

 l_res = [10;20;20;40;30;60]

但这似乎不起作用。我得到的类型是 let f l1 l2 = List.map (fun y -> (List.map (fun x -> x * y) l1) l2 ,但我想要f : int list -> int list -> int list list

我尝试了许多不同的方法,我觉得我过度复杂。

我错过了什么?

3 个答案:

答案 0 :(得分:4)

你遗失的是List.map f [a; b; c]给出了[f a; f b; f c]所以你从函数中得到的将是

f [a; b; c] [d; e] = [[ad; ae]; [bd; be]; [cd; ce]]

但你想要

 f [a; b; c] [d; e] = [ad; ae; bd; be; cd; ce]

所以你需要使用另一个迭代器,

 let f l1 l2 = 
   let res = List.fold_left (fun acc x ->
     List.fold_left (fun acc y -> (x * y) :: acc) acc l2
   ) [] l1 in
   List.rev res

或展平你的结果:

val concat : 'a list list -> 'a list
     

连接列表列表。论证的要素都是   连接在一起(以相同的顺序)给出结果。不   tail-recursive(参数的长度+最长的长度   子列表)。

 val flatten : 'a list list -> 'a list
     

与concat相同。不是尾递归(参数的长度+长度)   最长的子列表。)

答案 1 :(得分:2)

一些Core - 风味的答案:

open Core.Std

let f1 l1 l2 =
  List.map (List.cartesian_product l1 l2) ~f:(fun (x, y) -> x * y)

let f2 l1 l2 =
  List.concat_map l1 ~f:(fun x -> List.map l2 ~f:(fun y -> x * y))

let f4 l1 l2 =
  let open List.Monad_infix in
  l1 >>= fun x ->
  l2 >>| fun y ->
  x * y

显式的最后一个答案(可以说是隐含的另外两个答案)使用了列表monad,这是一个教科书用例。我在电池中找不到列表monad,这可能不是那么令人惊讶,因为它比选项或结果monad更少使用。

答案 2 :(得分:1)

let f l1 l2 =  
  let multiply x = List.map (( * )x) l2 in
  l1 |> List.map multiply
     |> List.concat