2011-02-02 15 views
7

Duplicar posibles:
Haskell: difference between . (dot) and $ (dollar sign)

Ok entiendo que esto:

f(g(x)) 

puede reescribirse:

f $ g(x) 

y también se puede escribir:

f . g(x) 

Lo que no comprenden totalmente es donde los dos no se superponen en la funcionalidad. Yo conceptualmente entiendo que no se superponen por completo, pero ¿alguien podría aclarar esto para mí de una vez?

+1

Mira, en realidad no puedes escribir como en tu segundo ejemplo. Tryi ghci! – fuz

+6

Además, los paréntesis no son necesarios (y no se recomiendan) para las llamadas a funciones. En resumen, los ejemplos deben ser 'f (g x)', 'f $ g x' y' (f. G) x'. – delnan

+0

@delhan o 'f. g $ x' – alternative

Respuesta

21
Prelude> :t ($) 
($) :: (a -> b) -> a -> b 
Prelude> :t (.) 
(.) :: (b -> c) -> (a -> b) -> a -> c 

$ se aplica una función a un valor. . compone dos funciones.

Así que puedo escribir f $ g x que es "aplicar f a (g de x)" o f . g $ x que es "aplicar la composición de fyg a x". Un estilo común es acumular puntos en la izquierda con un dólar al final. La razón es que f $ g $ x significa lo mismo que f . g $ x pero la expresión f $ g en sí misma es a menudo de sentido (de hecho, posiblemente un error de tipo) mientras que la expresión f . g significa "la composición de f y g"

+3

'f $ g' es perfectamente posible y está bien tipado para innumerables' f' y 'g' (considere' (\ f -> f 0) $ (\ x -> x + 1) '), es exactamente idéntico a 'fg'. De lo contrario, correcto. – delnan

+0

@delnan No puedo pensar en un 'f $ g' que esté bien tipado por sí mismo * y * en el contexto de' f $ g $ x'. Pero eso podría ser un fracaso de la imaginación. – sclv

+1

Si 'f' toma y devuelve una función, es posible. Ejemplo: 'const (f :: a -> b) $ (g :: c -> d) :: a -> b' y' const (f :: a -> b) $ (g :: c -> d) $ (... :: a) :: b'. Por supuesto, es mucho más difícil encontrar un ejemplo significativo/real, pero w.r.t. el sistema de tipos no tiene nada de excepcional. – delnan

1

"f $ gx "no se puede reescribir a" f. gx ". De hecho, el compilador ni siquiera aceptará la segunda función, porque "(.)" Tiene el tipo "(b -> c) -> (a -> b) -> (a -> c)". Es decir, el segundo argumento debe ser una función, pero "g x" es un valor, no una función.

+0

'g x' será una función para (curried) 2-or-more-ary' g', p. Ej. 'const 0'. – delnan

+0

@delnan: Sí, pero supuse que era unario por la forma en que lo usó. – keiter

14

Adicionalmente a lo que ya se dijo, se necesita el $ como "pegamento aplicación de función" en casos como éste:

map ($3) [(4+),(5-),(6*),(+4),(*5),(^6)] 
--[7,2,18,7,15,729] 

Ni (.3) ni (3) funcionará en el ejemplo.

+3

+1 - gran adición a la discusión – Ramy