haskell - maximum - ¿Cuándo debería usar $(y siempre se puede reemplazar con paréntesis)?
maximum in haskell (5)
Según lo que estoy leyendo, $
se describe como "aplica una función a sus argumentos". Sin embargo, no parece funcionar bastante como (apply ...)
en Lisp, porque es un operador binario, así que realmente lo único que parece es que ayuda a evitar paréntesis a veces, como foo $ bar quux
lugar de foo (bar quux)
. ¿Lo estoy entendiendo bien? ¿La última forma se considera "mal estilo"?
En su mayoría lo entiendes bien, es decir, aproximadamente el 99% del uso de $ es para ayudar a evitar paréntesis, y sí, parece ser preferible a paréntesis en la mayoría de los casos.
Nota, sin embargo:
> :t ($) ($) :: (a -> b) -> a -> b
Es decir, $ es una función; como tal, se puede pasar a funciones, compuestas con, y cualquier otra cosa que quieras hacer con él. Creo que lo he visto usado por personas que antes usaban combinadores.
La documentación de ($) responde su pregunta. Lamentablemente, no figura en la documentación generada automáticamente del Preludio .
Sin embargo, se enumera en el código fuente que puede encontrar aquí:
http://darcs.haskell.org/packages/base/Prelude.hs
Sin embargo, este módulo no define ($) directamente. El siguiente, que es importado por el primero, hace:
http://darcs.haskell.org/packages/base/GHC/Base.lhs
Incluí el código relevante a continuación:
infixr 0 $
...
-- | Application operator. This operator is redundant, since ordinary
-- application @(f x)@ means the same as @(f ''$'' x)@. However, ''$'' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- > f $ g $ h x = f (g (h x))
--
-- It is also useful in higher-order situations, such as @''map'' (''$'' 0) xs@,
-- or @''Data.List.zipWith'' (''$'') fs xs@.
{-# INLINE ($) #-}
($) :: (a -> b) -> a -> b
f $ x = f x
Muchas buenas respuestas arriba, pero una omisión:
$
no siempre se puede reemplazar por paréntesis
Pero cualquier aplicación de $
se puede eliminar mediante el uso de paréntesis , y cualquier uso de ($)
se puede reemplazar por id
, ya que $
es una especialización de la función de identidad . Los usos de (f$)
se pueden reemplazar por f
, pero un uso como ($x)
(tomar una función como argumento y aplicarlo a x
) no tiene ningún reemplazo obvio que yo vea.
$
se prefiere entre paréntesis cuando la distancia entre los paréntesis de apertura y cierre sería superior a la buena legibilidad, o si tiene varias capas de paréntesis anidados.
Por ejemplo
i (h (g (f x)))
puede ser reescrito
i $ h $ g $ f x
En otras palabras, representa la aplicación de función asociativa derecha. Esto es útil porque la aplicación de función ordinaria se asocia a la izquierda, es decir, la siguiente
i h g f x
... puede ser reescrito de la siguiente manera
(((i h) g) f) x
Otros usos útiles de la función ($)
incluyen comprimir una lista con ella:
zipWith ($) fs xs
Esto aplica cada función en una lista de funciones fs
a un argumento correspondiente en la lista xs
, y recopila los resultados en una lista. Contraste con la sequence fs x
que aplica una lista de funciones fs
a un único argumento x
y recopila los resultados; y fs <*> xs
que aplica cada función en la lista fs
a cada elemento de la lista xs
.
Si veo tu pregunta y las respuestas aquí, Apocalisp y tú tienen razón:
-
$
se prefiere entre paréntesis en ciertas circunstancias (ver su respuesta) -
foo (bar quux)
ciertamente no es un mal estilo!
Además, por favor verifique la diferencia entre. (punto) y $ (signo de dólar) , otra pregunta SO muy relacionada con la suya.