2016-08-25 3 views
4

Я вернулся к кодированию в OCaml, и я так сильно его пропустил. Я пропустил это так, что полностью потерял рассуждения на этом языке, и сегодня я ударил по стене.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, но я хочу f : int list -> int list -> int list

Я пробовал уже много разных подходов, я чувствую, что я усложняю.

Что я пропустил?

ответ

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 

Concatenate список списков. Элементами аргумента являются все , объединенные вместе (в том же порядке), чтобы дать результат. Not tail-recursive (длина аргумента + длина самого длинного подписок).

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

То же, что и concat. Не хвост-рекурсивный (длина аргумента + длина самый длинный под-список).

+0

Вы совершенно правы. Я делал что-то действительно не так, и я не попадал туда с ручкой и бумагой. Спасибо за понимание! –

+0

Добро пожаловать. Я взял на себя смелость, чтобы отредактировать сообщение, чтобы сделать его более ясным. ;-) Добро пожаловать в OCaml! – Lhooq

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

Некоторые Core -flavoured ответы:

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 

Последний ответ явно (и, возможно, два других ответов неявно) использует список монады, что это является использование учебник случай , Я не смог найти список монады в Batteries, что, возможно, не так удивительно, поскольку оно гораздо менее широко используется, чем (скажем) вариант или монументы результата.

Смежные вопросы