Получение длины списка с помощью комбинаторов f # - PullRequest
0 голосов
/ 04 ноября 2018
let length (l : 'a list) =
  let mutable counter = 0
  for i in l do
    counter <- counter + 1
  counter

let list1 = [ 10; 25; 34; 45; 78 ]
length list1

Я могу получить длину списка, используя приведенный выше фрагмент кода (на F #), но мне интересно, как я могу сделать этот точный код с помощью комбинаторов. Если бы кто-нибудь мог помочь, это было бы здорово, спасибо!

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Как уже упоминалось Vidas, вы можете просто использовать встроенную функцию List.length, которая является лучшим способом сделать это на практике. Однако, если вас интересуют дополнительные параметры, тогда основной альтернативой является использование рекурсии:

let rec length l = 
  match l with 
  | [] -> 0
  | x::xs -> 1 + (length xs)

Это не написано с использованием комбинаторов, но это основной функциональный шаблон. Общий шаблон функции фиксируется функцией fold, которая позволяет (в основном) указать две ветви сопоставления с шаблоном. Используя fold вы можете написать:

let list1 = [ 10; 25; 34; 45; 78 ]
List.fold (fun s x -> s + 1) 0 list1

Это говорит о том, что начальное состояние 0, и для каждого элемента мы увеличиваем состояние s на 1 - так что результатом будет длина списка.

Если вы хотите сделать что-то совершенно безумное, вы можете попробовать заменить функцию fun s x -> s + 1 на функцию, составленную с использованием комбинаторов. Это сделает ваш код нечитаемым (и никто никогда не должен этого делать), но интересно подумать, как это сделать. Вам может понадобиться вспомогательная функция, которая принимает функцию, два аргумента и передает два аргумента функции в виде кортежа:

let tuple f = fun a b -> f (a, b)

Теперь вы можете написать что-то вроде приведенного ниже кода - который использует как можно больше стилей комбинаторов, но его довольно сложно расшифровать.

List.fold (tuple (fst >> (+) 1)) 0 list1

Итак, List.length - это путь: -).

0 голосов
/ 04 ноября 2018

Я предполагаю, что вы просите

Seq.length list1
...