Pregunta

Hace un tiempo, pregunté a pregunta sobre $ , y obtuve respuestas útiles; de hecho, pensé que entendía cómo usarlo.

Parece que estaba equivocado :(

Este ejemplo aparece en un tutorial:

instance Monad [] where
   xs >>= f = concat . map f $ xs

No puedo por mi vida ver por qué $ se usó allí; ghci tampoco me está ayudando, ya que incluso las pruebas que hago allí parecen mostrar equivalencia con la versión que simplemente omitiría el $. ¿Alguien puede aclarar esto por mí?

¿Fue útil?

Solución

El $ se usa aquí porque tiene una prioridad más baja que la aplicación de función normal. Otra forma de escribir este código es así:

instance Monad [] where
   xs >>= f = (concat . map f) xs

La idea aquí es construir primero una función ( concat. map f ) y luego aplicarla a su argumento ( xs ). Como se muestra, esto también se puede hacer simplemente poniendo paréntesis alrededor de la primera parte.

Tenga en cuenta que no es posible omitir el $ en la definición original, ya que provocará un error de tipo. Esto se debe a que el operador de composición de funciones (el . ) tiene una precedencia más baja que la aplicación de función normal, convirtiendo la expresión en:

instance Monad [] where
  xs >>= f = concat . (map f xs)

Lo cual no tiene sentido, porque el segundo argumento para el operador de composición de funciones no es una función en absoluto. Aunque la siguiente definición tiene sentido:

instance Monad [] where
  xs >>= f = concat (map f xs)

Por cierto, esta es también la definición que preferiría, porque me parece mucho más clara.

Otros consejos

Me gustaría explicar por qué, en mi humilde opinión, este no es el estilo utilizado allí:

instance Monad [] where
  xs >>= f = concat (map f xs)

concat. map f es un ejemplo de la llamada escritura de estilo libre de puntos; donde pointfree significa "sin el punto de aplicación". Recuerde que en matemáticas, en la expresión y = f (x) , decimos que f se aplica en el punto x . En la mayoría de los casos, puede hacer un paso final, reemplazando:

f x = something $ x

con

f = something

como f = concat. map f , y este es en realidad un estilo sin puntos. Lo que está más claro es discutible, pero el estilo sin puntos ofrece un punto de vista diferente que también es útil, por lo que a veces se usa incluso cuando no es exactamente necesario.

EDITAR: he reemplazado sin sentido por punto y arreglé algunos ejemplos, después del comentario de Alasdair, a quien debo agradecer.

La razón por la que $ se usa aquí es debido a la firma de tipo de (.):

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

Aquí tenemos

map f :: [a] -> [[b]]

y

concat :: [[b]] -> [b]

Entonces terminamos con

concat . map f :: [a] -> [b]

y el tipo de (.) podría escribirse como

(.) :: ([[b]] ??- > [b]) - > ([a] - > [[b]]) - > [a] - > [b]

Si tuviéramos que usar concat. map f xs , lo veríamos

map f xs :: [[b]]

Y así no se puede usar con (.). (el tipo debería ser (.) :: (a - > b) - > a - > b

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top