Я новичок в f #
Я пытаюсь вычислить декартовы произведения списка чисел. Я "заимствовал" это.
let xs = [1..99]
let ys = [1..99]
seq {for x in xs do for y in ys do yield x * y}
Есть ли лучший или более элегантный способ?
Гэри
Я новичок в f #
Я пытаюсь вычислить декартовы произведения списка чисел. Я "заимствовал" это.
let xs = [1..99]
let ys = [1..99]
seq {for x in xs do for y in ys do yield x * y}
Есть ли лучший или более элегантный способ?
Гэри
Другой возможностью для решения проблемы, основанной на функциональности, предоставляемой модулем List, будет следующее:
let xs = [1..99]
let ys = [1..99]
let zs = xs |> List.collect (fun x -> ys |> List.map (fun y -> x*y))
что позволяет избежать дополнительных вызовов .concat и также выполнять задание.
Но я бы придерживался вашего решения. Он должен быть самым читаемым, который является настоящим спикером. (Просто попробуйте прочитать коды вслух. Твое вполне понятно, а Нолдорины или мои нет.)
Отказ от ответственности: у меня нет машины с установленным текущим F #, поэтому я не могу проверить свой код. В принципе, если вы украдете sequence
из Haskell, вы можете написать свою программу как
let cartesian = sequence >> List.map product
и запустите его как
cartesian [[1..99]; [1..99]]
Вот как писать sequence
. Это обобщенная версия выражения последовательности, которое вы написали. Он просто обрабатывает неограниченное количество списков: { for x in xs do for y in ys do for z in zs ... yield [x;y;z;...] }
.
let rec sequence = function
| [] -> Seq.singleton []
| (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) }
// also you'll need product to do the multiplication
let product = Seq.fold_left1 ( * )
Затем вы можете написать свою программу как
let cartesian xs ys = [xs; ys] |> sequence |> List.map product
// ... or one-argument, point-free style:
let cartesian' = sequence >> Seq.map product
Возможно, вам придется изменить некоторые Seq
на List
s.
Тем не менее, количество людей, которые могут угадать смысл вашего общего недопонимания списков, вероятно, намного больше, чем распознает имя sequence
, поэтому вам, вероятно, лучше со списком понимания. sequence
пригодится в любое время, когда вы хотите запустить весь список вычислений.
Действительно, есть несколько более элегантный способ (по крайней мере в функциональном смысле) для вычисления декартовых произведений, который использует функции, которые существуют в классе List
. (Здесь нет необходимости включать в себя последовательности или циклы, по крайней мере, не напрямую.)
Попробуйте следующее:
let xs = [1..99]
let ys = [1..99]
xs |> List.map(fun x -> ys |> List.map(fun y -> x * y)) |> List.concat
Казалось бы, немного длиннее, хотя и более функциональный по стилю.