Есть ли в OCaml оператор композиции инфиксных функций?
Просто быстрый вопрос. Мне интересно, есть ли в OCaml оператор композиции инфиксных функций, определенный в стандартной библиотеке (или в ядре Джейн Стрит, или в Батареях), такой как функция (.) В Haskell, которая экономит нам много скобок, так как мы можем написать (f . g . h) x
вместо менее привлекательного f (g (h x)))
,
Спасибо, ребята.
6 ответов
Ответ здесь такой же, как и для flip
:-). Состав функций не определен в стандартной библиотеке OCaml. В данном случае я не скучаю по этому время от времени, я скучаю по нему все время.
Проект OCaml Batteries Included определяет состав функции (в том порядке, в котором вы ее задаете) с помощью оператора -|
в BatStd
модуль. Как указывает Лукстафи (см. Ниже), этот оператор, по-видимому, изменится на %
в будущем выпуске батарей. (Я подтвердил это в их исходном дереве.)
Насколько я вижу, проект Jane Street Core не определяет оператор композиции функций. Определяет функцию compose
в Fn
модуль.
Я просто хочу добавить, что оператор довольно легко включить, в F# он просто определяется как:
let (<<) f g x = f(g(x));;
который имеет тип подписи: val ( << ) : f:('a -> 'b) -> g:('c -> 'a) -> x:'c -> 'b
делать именно то, что вам нужно...
(f << g << h) x = f(g(h(x))
так что вам не нужен проект батареи, если вам не нужно
Я хотел бы добавить, что причина, по которой это выглядит <<
как вы можете догадаться, потому что >>
Оператор делает обратное:
let (>>) f g x = g(f(x));;
(f >> g >> h) x = h(g(f(x))
Есть Fn.compose
функция в ядре, но это не инфиксный оператор. Кроме того, он реализован как обычная функция и имеет накладные расходы времени выполнения.
На практике довольно удобно использовать трубочный оператор. Он не имеет накладных расходов времени выполнения, реализованных непосредственно в компиляторе (начиная с 4.00). См. Оптимизированные операторы труб для более подробной информации.
Оператор трубы доступен как '|>' в Core. Итак, вы можете переписать ваше выражение следующим образом: h x |> g |> f
Использование инфиксного оператора композиции, похоже, не рекомендуется. (см. это обсуждение).
Ты можешь написать f @@ g @@ h x
вместо f (g (h x)))
,
В контейнерах (еще одна замена stdlib для Ocaml) оператор композиции функций называется %
и может быть найден в модуле CCFun:
open Containers
open Fun
let is_zero n = (n = 0)
let nonzeros = List.filter (not % is_zero) [0;1;2;3;0]
Может быть, это может помочь вам.
let identite f = f
let (>>) = List.fold_right identite
тестовое задание:
# let f=fun x-> x+1 and
g=fun x-> x*2 and
h=fun x-> x+3;;
# [f;g;h] >> 2;;
- : int = 11