В идеале, алгоритм должен быть ленивым-оценивать ... создание подпоследовательности для каждого элемента является убийцей производительности
Ленивый означает медленный, но вот решение с использованием ленивых списков:
let (++) = LazyList.consDelayed
let rec merge xs ys () =
match xs, ys with
| Cons(x, xs'), Cons(y, _) when x<y -> x ++ merge xs' ys
| Cons(x, _), Cons(y, ys') -> y ++ merge xs ys'
| Nil, xs | xs, Nil -> xs
Я думаю, что под "отложенной оценкой" вы подразумеваете, что хотите, чтобы объединенный результат генерировался по запросу, поэтому вы также можете использовать:
let rec merge xs ys = seq {
match xs, ys with
| x::xs, y::_ when x<y ->
yield x
yield! merge xs ys
| x::_, y::ys ->
yield y
yield! merge xs ys
| [], xs | xs, [] -> yield! xs
}
Как вы говорите, этоочень неэффективно.Однако решение на основе seq
не должно быть медленным.Здесь Seq.unfold
ваш друг и может сделать это в 4 раза быстрее по моим измерениям:
let merge xs ys =
let rec gen = function
| x::xs, (y::_ as ys) when x<y -> Some(x, (xs, ys))
| xs, y::ys -> Some(y, (xs, ys))
| [], x::xs | x::xs, [] -> Some(x, ([], xs))
| [], [] | [], [] -> None
Seq.unfold gen (xs, ys)