2011-03-26 18 views
9

Entiendo los conceptos básicos de la composición de funciones en F #, como, por ejemplo, se describe here.¿Qué me estoy perdiendo: es la composición de funciones con múltiples argumentos posibles?

Tal vez me falta algo. Los >> y << operadores parecen haber sido definido con la suposición de que cada función sólo toma un argumento:

> (>>);; 
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:[email protected]> 
> (<<);; 
val it : (('a -> 'b) -> ('c -> 'a) -> 'c -> 'b) = <fun:[email protected]> 

lo que me gustaría hacer, sin embargo, es algo así como lo siguiente:

let add a b = a + b 
let double c = 2*c 
let addAndDouble = add >> double // bad! 

Pero aunque la salida add es del tipo requerido para la entrada double, es rechazada.

sé que puedo reescribir añadir con el argumento una tupla:

let add (a,b) = a + b 

O puedo escribir un nuevo operador para cada número de posibles argumentos a la primera función:

let inline (>>+) f g x y = g (f x y) 
let doubleAdd = add >>+ double 

Pero parece tonto! ¿Hay una mejor manera que me he perdido?

Respuesta

11

Lo que quiere no es totalmente irrazonable, pero no habría forma de indicar el tipo de un operador de composición generalizada dentro del tipo de F # sistema. Es decir, no hay una buena forma de unificar

(>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c 

y

(>>+) : ('a -> 'b -> 'c) -> ('c -> 'd) -> 'a -> 'b -> 'd 

(por no hablar de la infinidad de versiones superiores Arity). Por lo tanto, no tiene otra alternativa que definir sus propios operadores adicionales. En la práctica, a menudo encuentro código escrito en el estilo "puntiagudo" let f x y = add x y |> double más legible que el let f = add (>>+) double sin puntos/"sin sentido" de todos modos.

+1

acuerdo, estilo ojival es a menudo más fácil de leer. – Laurent

+2

Especialmente cuando comienzas a tener que "voltear" tus funciones. –

4

Mire los tipos de >> y << que publicó anteriormente. por ejemplo:

> (>>);; 
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:[email protected]> 

Se necesitan dos funciones y un valor ('a) y devuelve otro valor. Necesita algo que tenga dos funciones y 2 valores. Por lo tanto, tanto >> como << no tienen la firma de tipo correcta.

Su implementación no es para nada tonta. Es solo que su requerimiento no sale de la caja en las bibliotecas de F #. Agradezca que tenga un lenguaje que le permita definir sus propios operadores como este :)

3

¿Qué le parece pasar una pila de argumentos?

let add = function x :: y :: t -> x + y :: t 
let double = function x :: t -> 2 * x :: t 

A continuación, puede componer funciones Arity arbitrarias:

let doubleAdd = add >> double 

Y funciona:

> doubleAdd [7; 14] 
42 

(véase también F# Function Composition with multiple input parameters)

Cuestiones relacionadas