2011-02-14 18 views
8

¿Cómo puedo definir una función compuesta en un lenguaje funcional, en particular con Ocaml? Por ejemplo, si escribo una función que calcula la negación del resultado de otra función, es decir: not(f(x)) donde f(x) devuelve un valor booleano. ¿Cómo puedo definirlo?Funciones compuestas en ocaml

Respuesta

12

dado alguna función f, que tiene el tipo:

f: 'a -> bool 

desea ser capaz de generar otra función para envolverlo para negar el resultado. Vamos a considerar el tipo para esta nueva función, vamos a llamarlo negated (no estoy usando not ya que es el nombre de una orden interna):

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

¿Por qué es este tipo? ¿Por qué no 'a -> bool? Bien, recuerde, queremos que esta nueva función tome una función existente y devuelva una nueva función con el mismo tipo que hace algo diferente. Para verlo más claro, puedes pensarlo así: ('a -> bool) -> ('a -> bool) que es equivalente.

Ahora, dadas estas limitaciones, ¿cómo podemos escribir la función negated?

let negated f = ?? 

Bueno, primero tenemos que tener en cuenta que esta función tiene que devolver una función:

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

¿Qué sigue? Bien, sabemos que la nueva función que creamos debería llamar a nuestra función envuelta con el argumento y negarla. Hagamos eso, llame a la función con el argumento: f x, y anótelo: not (f x). Eso nos da la definición última función:

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

Vamos a ver en acción:

# 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

No estoy seguro exactamente lo lejos que está mirando para ir aquí - el código que escribió funcionará multa. Así que voy a dar un simple paso a paso sobre cómo escribir estas cosas desde cero. La negación simple es:

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

Puede cómo escribir not (f x) y se le dará la negación del resultado de f x.

Para una función que compone funciones, puede utilizar:

let comp f g x = f (g x) 

Entonces que podemos hacer:

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

let odd = comp not even 
+0

Y se puede definir 'comp' como operador, por ejemplo:' let ($) f g = function x -> f (g x) let odd = not $ even' – ygrek

+0

@newacct: ¿Eh? Lo que Ygrek publicó es correcto OCaml por lo que puedo decir, aunque no estoy muy seguro de por qué escribiría 'let ($) f g = function x ...' en lugar de simplemente 'let ($) f g x = ...'. – Chuck

+1

solo una cuestión de estilo – ygrek

3

Wow, qué pasa con todas estas respuestas excesivamente complicados?¿Qué tiene de malo:

let compose f g x = g (f x) 

Para obtener su g(x) = not(f(x)), suponiendo que tiene un f : 'a -> bool:

let g = compose not f 

Además, se pueden hacer cosas interesantes como:

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 

Ahora el composite_function tiene el tipo de int -> int, y su definición efectiva es:

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

EDITAR: Oh, supongo que Chuck realmente hizo esto. Probablemente no debería haber desnatado. En cualquier caso, me gusta doblar sobre la función de redacción, así que voy a seguir así. : p