Pregunta

Estaba intentando implementar la función.

every :: (a -> IO Bool) -> [a] -> IO Bool 

cual fue el tema de esta pregunta.Intenté hacer esto sin recursividad explícita.Se me ocurrió el siguiente código

every f xs = liftM (all id) $ sequence $ map f xs

Mi función no funcionó porque no era perezosa (lo cual era requerido en la pregunta), así que no hay votos positivos :-).

Sin embargo, no me detuve ahí.Intenté hacer la función. sin puntos para que fuera más corto (y quizás incluso más fresco).Desde los argumentos f y xs son los últimos en la expresión que acabo de soltar:

every = liftM (all id) $ sequence $ map 

Pero esto no funcionó como se esperaba, de hecho no funcionó en absoluto:

    [1 of 1] Compiling Main             ( stk.hs, interpreted )

    stk.hs:53:42:
        Couldn't match expected type `[m a]'
               against inferred type `(a1 -> b) -> [a1] -> [b]'
        In the second argument of `($)', namely `map'
        In the second argument of `($)', namely `sequence $ map'
        In the expression: liftM (all id) $ sequence $ map
    Failed, modules loaded: none.

¿Porqué es eso?Tenía la impresión de que era posible simplemente eliminar los argumentos de la función final, que básicamente es de lo que se trata el curry.

¿Fue útil?

Solución

La definición de $ es

f $ x = f x

Vamos plenamente su función de un paréntesis:

every f xs = (liftM (all id)) (sequence ((map f) xs))

y su versión al curry:

every = (liftM (all id)) (sequence map)

Como habrá notado, estos no son idénticos. Sólo se puede caer detrás de argumentos de la función cuando son lo último que se aplica. Por ejemplo,

f x = g c x

es en realidad

f x = (g c) x

y la aplicación de (g c) x ocupa el último lugar, para que pueda escribir

f = g c

Uno de los dibujos con el operador de la aplicación $ es que a menudo se convierte en el operador de composición. en versiones-puntos libres. Esto se debe a

f $ g $ x

es equivalente a

(f . g) $ x

Por ejemplo,

every f xs = liftM (all id) $ sequence $ map f xs

puede convertirse

every f xs = (liftM (all id) . sequence . map f) xs

momento en el que puede caer xs:

every f = liftM (all id) . sequence . map f

Eliminando el argumento f es más difícil, ya que se aplica antes de que el operador de composición. Vamos a usar la definición de puntos de http://www.haskell.org/haskellwiki/Pointfree :

dot = ((.) . (.))

Con los puntos, esto es

(f `dot` g) x = f . g x

y es exactamente lo que tenemos que hacer todos los puntos totalmente libre:

every = (liftM (all id) . sequence) `dot` map

Lamentablemente, debido a las restricciones en el sistema de tipos de Haskell, ésta necesita una firma de tipo explícito:

every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top