2012-01-06 14 views
15

Creo que entiendo cómo funcionan los funtores aplicativos en Haskell y los estoy usando para tipos de datos básicos (Tal vez, O bien ...). Sin embargo, encontré this question con el siguiente ejemplo:¿Qué functor aplicativo se usa para pasar parámetros compartidos?

withPool pool = bracket (takeConn pool) (putConn pool) 

puede reescribirse en estilo aplicativo:

withPool = bracket <$> takeConn <*> putConn 

Me sorprendió que compila y de hecho funciona como se esperaba, pero podría alguien me cuales Aplicativo decirle Functor se usa para esto y ¿cómo se define?

Actualización: Creo que descubrí cómo funciona, pero no tengo idea de dónde está definido.

Respuesta

17

Unificar f = (a ->) en las firmas de tipos:

fmap :: (b -> c) -> (a -> b) -> (a -> c) 
pure :: b -> (a -> b) 
(<*>) :: (a -> b -> c) -> (a -> b) -> (a -> c) 

La única razón por las declaraciones son sintácticamente diferentes, ((->) a) vs (a ->), es que no se les permite tomar las secciones en el nivel de tipo. Así que terminan con estos, después de los tipos que persiguen:

instance Functor ((->) a) where 
    fmap = (.) 

instance Applicative ((->) a) where 
    pure = const 
    f <*> g = \x -> f x $ g x 

Estoy bastante seguro de la instancia Functor está en Data.Functor, y la instancia Applicative está en Control.Applicative. La instancia Monad para ((->) a) es la única en un lugar extraño, en Control.Monad.Instances, en lugar de Control.Monad. Al menos si recuerdo correctamente.

+9

Por lo que vale, esta es de hecho la mónada del lector, menos un envoltorio 'newtype' - el" parámetro compartido "aquí es el mismo que el" entorno "para' Reader'. De manera similar, 'Either err' es la mónada de error y' (,) w' es writer. –

+0

@ C.A.McCann Vale la pena señalar, y lo olvidé. Gracias por agregar eso. – Carl

Cuestiones relacionadas