2016-08-25 24 views
4

私はOCamlでコーディングに戻っています。私はそれを逃してしまったので、私はこの言葉で私の推論を完全に失いました。OCaml:リスト内の要素の組み合わせ、関数的推論

私がしたいことは、n個のリストのセットの間の要素の組み合わせです。 私はまず、任意のサイズの2つのリストの間で要素の組み合わせを試みることによって問題を分解しました。

リストを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; b; c] [d; e] = [[ad; ae]; [bd; be]; [cd; ce]] 

となりますので、[f a; f b; f c]を与えていますが、

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

をしたいということです、 すなわち

またはあなたの結果を平らにする:

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

はリストのリストを連結します。引数の要素はすべて で連結され(同じ順序で)結果が得られます。 tail-recursive(引数の長さ+最長の サブリストの長さ)。

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

コンカットと同じです。テール再帰的ではありません(引数の長さ+長さ 最長のサブリスト)。

+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 

明示的に最後の答え(および暗黙的に間違いなく他の二つの答えが)、これはの教科書のユースケースであるリストモナドを利用します。私は電池でリストのモナドを見つけることができませんでした。それはオプションや結果のモナドよりもはるかに広く使われていないので、あまり驚くことではないかもしれません。