Композитные функции в ocaml - PullRequest
       48

Композитные функции в ocaml

8 голосов
/ 15 февраля 2011

Как определить составную функцию на функциональном языке, в частности, с помощью Ocaml? Например, если я напишу функцию, которая вычисляет отрицание результата другой функции, то есть: not(f(x)), где f(x) возвращает логическое значение. Как я могу это определить?

Ответы [ 3 ]

12 голосов
/ 15 февраля 2011

Учитывая некоторую функцию f, которая имеет тип:

f: 'a -> bool

вы хотите иметь возможность сгенерировать другую функцию, чтобы обернуть ее, чтобы свести на нет результат. Давайте рассмотрим тип для этой новой функции, назовем ее negated (я не использую not, поскольку это имя встроенной функции):

negated: ('a -> bool) -> 'a -> bool

Почему это тип? Почему бы не 'a -> bool? Хорошо помните, мы хотим, чтобы эта новая функция принимала существующую функцию и возвращала новую функцию того же типа, которая делает что-то другое. Чтобы было понятнее, вы можете думать об этом так: ('a -> bool) -> ('a -> bool), что эквивалентно.

Итак, теперь, учитывая эти ограничения, как мы можем написать функцию negated?

let negated f = ??

Ну, во-первых, мы должны учитывать, что эта функция должна возвращать функцию:

let negated f = (fun x -> ??)

Что дальше? Что ж, мы знаем, что новая функция, которую мы создаем, должна вызывать нашу упакованную функцию с аргументом и отрицать ее. Давайте сделаем это, вызовем функцию с аргументом: f x и отвергнем ее: not (f x). Это дает нам окончательное определение функции:

let negated f = (fun x -> not (f x))

Давайте посмотрим на это в действии:

# let f x = x < 5;;
val f : int -> bool = <fun>
# f 2;;
- : bool = true
# f 8;;
- : bool = false
# let negated f = (fun x -> not (f x));;
val negated : ('a -> bool) -> 'a -> bool = <fun>
# let g = negated(f);;
val g : int -> bool = <fun>
# g 2;;
- : bool = false
# g 8;;
- : bool = true
5 голосов
/ 15 февраля 2011

Я точно не знаю, как далеко вы собираетесь зайти - код, который вы написали, будет работать нормально.Поэтому я покажу простой шаг за шагом, как вы пишете этот материал с нуля.Простое отрицание просто:

let not = function
  | true -> false
  | false -> true

Вы можете написать not (f x), и оно даст вам отрицание результата f x.

Для функции, которая составляет функцииможно использовать:

let comp f g x = f (g x)

Итак, мы можем сделать:

let even n = match n mod 2 with
  | 0 -> true
  | _ -> false

let odd = comp not even
3 голосов
/ 13 сентября 2011

Ух ты, что со всеми этими слишком сложными ответами?Что не так с:

let compose f g x = g (f x)

Чтобы получить g(x) = not(f(x)), при условии, что у вас есть f : 'a -> bool:

let g = compose not f

Кроме того, вы можете делать такие классные вещи, как:

let composite_function =
   let id x = x in
   let transforms = [
      (fun n -> n + 1);
      (fun n -> n * 2);
      (fun n -> n * n)
   ] in
   List.fold_left compose id transforms

Теперь composite_function имеет тип int -> int, и его эффективное определение:

let composite_function n =
   let n2 = (n + 1) * 2 in
   n2 * n2

РЕДАКТИРОВАТЬ: О, я думаю, Чак действительно сделал это.Я, наверное, не должен был просто снять.В любом случае, мне нравится складывать над функцией compose, так что я буду продолжать в том же духе.: Р

...