Разный порядок аргументов для получения N-го элемента массива, списка или Seq

Есть ли веская причина для другого порядка аргументов в функциях, получающих N-й элемент массива, списка или Seq:

Array.get source index
List .nth source index
Seq  .nth index  source

Я хотел бы использовать оператор трубы, и это кажется возможным только с Seq:

s |> Seq.nth n

Есть ли способ иметь одно и то же обозначение с массивом или списком?

Ответ 1

Я не думаю о какой-либо хорошей причине для определения Array.get и List.nth таким образом. Учитывая, что трубопровод очень часто встречается в F #, они должны быть определены так, чтобы аргумент source пришел последним.

В случае List.nth это не сильно изменится, потому что вы можете использовать Seq.nth, а временная сложность по-прежнему O(n), где n - длина списка:

[1..100] |> Seq.nth 10

Не рекомендуется использовать Seq.nth для массивов, потому что вы теряете произвольный доступ. Чтобы сохранить O(1) время работы Array.get, вы можете определить:

[<RequireQualifiedAccess>]
module Array =
    /// Get n-th element of an array in O(1) running time
    let inline nth index source = Array.get source index

В общем случае, другой порядок аргументов можно облегчить с помощью функции flip:

let inline flip f x y = f y x

Вы можете использовать его непосредственно над функциями выше:

[1..100] |> flip List.nth 10
[|1..100|] |> flip Array.get 10

Ответ 2

Просто используйте оператор обратной трубы:

[1..1000] |> List.nth <| 42

Поскольку оба оператора оставлены ассоциативными, x |> f <| y анализируется как (x |> f) <| y, и это делает трюк.

Оператор обратной линии также полезен, если вы хотите удалить круглые скобки: f (very long expression) можно заменить на f <| very long expression.

Ответ 3

Так как Pad и bytebuster ответили на ваш последний вопрос, я сосредоточусь на том, почему.

Это основано на моих текущих знаниях, а не на исторических фактах.

Так как F #, полученный из OCaml и OCaml, имеет Array и List, но not Seq и F # использует | > для естественной конвейерной обработки и проверка типов и В OCaml отсутствует оператор pipleline, авторы F # сделали переключатель для Seq. Но, очевидно, чтобы быть обратно скомпонованными с OCaml, они не переключили все.