Чтобы прояснить некоторые вещи, разница между Seq.take
и Seq.truncate
(как указано @ sepp2k) заключается в том, что второй даст вам последовательность, которая возвращает самое большее число элементы, которые вы указали (но если длина последовательности меньше, это даст вам меньше элементов).
Сгенерированная последовательность функция Seq.take
сгенерирует исключение, если вы попытаетесь получить доступ к элементу за пределами длины исходного списка (обратите внимание, что функция Seq.take
не выдает исключение сразу, потому что результат генерируется лениво последовательность).
Кроме того, вам не нужно явно преобразовывать список в последовательность. Под обложкой list<'a>
- это класс .NET, который наследуется от типа seq<'a>
, который является интерфейсом. Тип seq<'a>
на самом деле является просто псевдонимом типа для IEnumerable<'a>
, поэтому он реализуется всеми другими коллекциями (включая массивы, изменяемые списки и т. Д.). Следующий код будет работать нормально:
let list = [ 1 .. 10 ]
let res = list |> Seq.take 5
Однако, если вы хотите получить результат типа list<int>
, вам нужно преобразовать последовательность обратно в список (поскольку список является более конкретным типом, чем последовательность):
let resList = res |> List.ofSeq
Я не уверен, почему библиотеки F # не предоставляют List.take
или List.truncate
. Я предполагаю, что цель состояла в том, чтобы избежать переопределения всего набора функций для всех типов коллекций, поэтому те, где реализация для последовательностей достаточно хороша при работе с более конкретным типом коллекции, доступны только в модуле Seq
(но это только мое предположение ...)