mundo - multiplos en haskell
¿Qué significa $/do en Haskell? (2)
Me gusta pensar en el signo $ como un reemplazo para el paréntesis.
Por ejemplo, la siguiente expresión:
take 1 $ filter even [1..10]
-- = [2]
¿Qué pasa si no ponemos los $? Entonces obtendría
take 1 filter even [1..10]
y el compilador ahora se quejaría, porque pensaría que estamos tratando de aplicar 4 argumentos a la función take
, con los argumentos siendo 1 :: Int
, filter :: (a -> Bool) -> [a] -> [a]
, even :: Integral a => a -> Bool
, [1..10] :: [Int]
.
Esto es obviamente incorrecto. Entonces, ¿qué podemos hacer en su lugar? Bueno, podríamos poner paréntesis alrededor de nuestra expresión:
(take 1) (filter even [1..10])
Esto no se reduciría a:
(take 1) ([2,4,6,8,10])
que luego se convierte en:
take 1 [2,4,6,8,10]
Pero no siempre queremos escribir paréntesis, especialmente las funciones comienzan a anidarse entre sí. Una alternativa es colocar el signo $
entre el par de paréntesis que iría, que en este caso sería:
take 1 $ filter even [1..10]
Cuando escribes funciones un poco más complejas, noto que $
se usa mucho, pero no tengo idea de qué es lo que hace.
$
es infijo "aplicación". Se define como
($) :: (a -> b) -> (a -> b)
f $ x = f x
-- or
($) f x = f x
-- or
($) = id
Es útil para evitar paréntesis adicionales: f (gx) == f $ gx
.
Una ubicación particularmente útil para él es para un "cuerpo lambda posterior" como
forM_ [1..10] $ /i -> do
l <- readLine
replicateM_ i $ print l
comparado con
forM_ [1..10] (/i -> do
l <- readLine
replicateM_ i (print l)
)
O, engañosamente, aparece seccionado a veces cuando se expresa "aplicar este argumento a cualquier función"
applyArg :: a -> (a -> b) -> b
applyArg x = ($ x)
>>> map ($ 10) [(+1), (+2), (+3)]
[11, 12, 13]