Понимание списка было бы самым простым способом сделать это:
let allpairs L =
[for x in L do
for y in L -> (x*y)]
Или без использования петель:
let pairs2 L = L |> List.collect (fun x -> L |> List.map (fun y -> (x*y)))
Редактировать в ответ на комментарий:
Вы можете добавить метод самопересекающегося расширения в список, подобный этому:
type Microsoft.FSharp.Collections.List<'a> with
member L.cross f =
[for x in L do
for y in L -> f x y]
Пример:
> [1;2;3].cross (fun x y -> (x,y));;
val it : (int * int) list =
[(1, 1); (1, 2); (1, 3); (2, 1); (2, 2); (2, 3); (3, 1); (3, 2); (3, 3)]
Я бы не использовал метод расширения в F # сам, это немного C # 'иш. Но это в основном потому, что я не чувствую, что в F # нужен свободный синтаксис, потому что я обычно объединяю свои функции в цепочку с операторами |
Мой подход заключается в расширении модуля List перекрестной функцией, а не самим типом:
module List =
let cross f L1 L2 =
[for x in L1 do
for y in L2 -> f x y]
Если вы сделаете это, вы можете использовать метод cross, как и любой другой метод List:
> List.cross (fun x y -> (x,y)) [1;2;3] [1;2;3];;
val it : (int * int) list =
[(1, 1); (1, 2); (1, 3); (2, 1); (2, 2); (2, 3); (3, 1); (3, 2); (3, 3)]
> List.cross (*) [1;2;3] [1;2;3];;
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]