OCaml
Функции более высокого порядка
Поиск…
Синтаксис
-
val (|>) : 'a -> ('a -> 'b) -> 'b -
val (@@) : ('a -> 'b) -> 'a -> 'b
Общие алгоритмы
Функции более высокого порядка могут использоваться для реализации общих алгоритмов, отказываясь от ответственности за предоставление конечных деталей пользователю. Например, List.sort ожидает функцию сравнения, которая позволяет реализовать различные способы сортировки. Здесь мы реализуем нечувствительную к регистру сортировку строк:
let string_case_insensitive_sort lst =
let case_insensitive_compare a b =
String.compare (String.lowercase a) (String.lowercase b)
in
List.sort case_insensitive_compare lst
В стандартной библиотеке имеется богатый список функций более высокого порядка, особенно в модуле « Список », например, List.fold_left и List.sort . Более сложные примеры можно найти в сторонних библиотеках. Хорошим примером является имитированный отжиг, реализованный в ocaml-gsl . Имитированный отжиг - это общая процедура оптимизации, которая параметризуется функцией, используемой для изучения множества состояний проблемы и функции ошибки (называемой здесь энергетической функцией).
Пользователи, знакомые с C ++, могут сравнить это с шаблоном стратегии .
Устранение системных ресурсов, даже когда возникает исключение
Функции более высокого порядка могут использоваться для обеспечения того, чтобы ресурсы системы были удалены, даже когда обработка вызывает исключение. Шаблон, используемый with_output_file позволяет обеспечить with_output_file разделение проблем: функции более высокого порядка с with_output_file заботятся об управлении системными ресурсами, связанными с манипулированием файлами, в то время как обработка f потребляет только выходной канал.
let with_output_file path f =
let c = open_out path in
try
let answer = f c in
(close_out c; answer)
with exn -> (close_out c; raise exn)
Давайте используем эту функцию более высокого порядка для реализации функции, записывающей строку в файл:
let save_string path s =
(with_output_file path) (fun c -> output_string c s)
Используя более сложные функции, чем fun c -> output_string cs можно сохранить более сложные значения. См. Например, модуль Marshal в стандартной библиотеке или библиотеку Yojson от Martin Jambon.
Операторы композиции
Двумя полезными функциями более высокого порядка являются двоичное приложение ( @@ ) и обратное приложение или «труба» ( |> ). Хотя с 4.01 они доступны в качестве примитивов, может быть поучительно их определить здесь:
let (|>) x f = f x
let (@@) f x = f x
Рассмотрим проблему приращения квадрата 3. Один из способов выразить, что вычисление таково:
(* 1 -- Using parentheses *)
succ (square 3)
(* - : int = 10 *)
(* where `square` is defined as: *)
let square x = x * x
Обратите внимание, что мы не могли просто сделать succ square 3 потому что (из-за лево-ассоциативности ), который уменьшился бы до бессмысленного (succ square) 3 . Используя приложение ( @@ ), мы можем выразить это без круглых скобок:
(* 2 -- Using the application operator *)
succ @@ square 3
(* - : int = 10 *)
Обратите внимание, как первая операция, выполняемая (а именно succ ), происходит сначала в выражении? Оператор обратного приложения ( |> ) позволяет нам, наоборот, обратить вспять это:
(* 3 -- Using the reverse-application operator *)
3 |> square |> succ
(* - : int = 10 *)
Число 3 теперь «проложено» через square а затем succ , в отличие от применения к square чтобы получить результат, к которому применяется succ .