Как сгладить ввод смешанных 'T и seq<' T> в один seq<'T>
Мне нужна функция, которая может принимать произвольное количество аргументов, каждый из которых может быть любого типа 'T
или же seq<'T>
, Внутри функции мне нужно обработать его как единый seq<'T>
со всеми входами, объединенными в том же порядке, в котором они поставляются.
Очевидным способом было получить что-то вроде:
module Test =
let flatten ([<ParamArray>] args) =
let flat = seq {
for a in args do
match box a with
| :? int as x -> yield x
| :? seq<int> as sq ->
for s in sq do
yield s
| _ -> failwith "wrong input type"
}
flat // this should be seq<int>
но я не могу заставить его работать в FSI даже в простейшем случае
let fl = Test.flatten 1;;
----------------------^
...: error FS0001: The type 'int' is not compatible with the type 'seq<'a>'
Что здесь не так и как заставить работать так, как нужно? Возможно, это можно сделать каким-то совершенно другим способом?
1 ответ
Из MSDN:
В F# массивы параметров могут быть определены только в методах. Их нельзя использовать в автономных функциях или функциях, определенных в модулях.
Поэтому вместо модуля объявляйте тип статическим методом.
open System
type Test() =
static member flatten ([<ParamArray>] args: obj[]) =
let flat = seq {
for a in args do
match box a with
| :? int as x -> yield x
| :? seq<int> as sq ->
for s in sq do
yield s
| _ -> failwith "wrong input type"
}
flat
Если у вас есть другие привязки let, вы все равно можете объявить модуль с тем же именем. Также обратите внимание, что во втором защитнике матча вы можете избежать for
цикл, выполнив:
| :? seq<int> as sq -> yield! sq
А также box
не требуется.