2012-07-17 16 views

Respuesta

27

Es bastante útil cuando se combina con Traversable.

getConst . traverse Const :: (Monoid a, Traversable f) => f a -> a 

Esa es la receta general para englobar un montón de cosas juntas. Fue uno de los casos de uso que me convenció de que valía la pena separar Applicative de Monad. Necesitaba cosas por el estilo generalizada elem

elem :: Eq x => x -> Term x -> Bool 

hacer ocurrir-comprobación de un Traversable Term parametrizada por la representación de variables libres. Seguí cambiando la representación de Term y estaba harto de modificar un trillón de funciones, algunas de las cuales estaban haciendo acumulaciones, en lugar de mapeos efectivos. Me alegré de encontrar una abstracción que cubriera ambos.

+0

http://www.soi.city.ac.uk/~ross/papers/Applicative.html sección 4 es una buena referencia para el truco transversal –

+0

No 'foldMap id' produce el mismo resultado con menos restricciones ('Plegable' en lugar de' Traversable')? –

+1

De hecho, es por eso que 'Plegable' existe. Sin embargo, es bastante útil que todo 'Traversable' sea' Plegable', siendo la anterior la construcción de 'foldMapDefault'. Enchufe: SHE admite 'DefaultSuperclassInstances', de modo que todo' Traversable' se establece de forma predeterminada por silencioso como 'Plegable'. – pigworker

6

Es útil cuando tiene una función o estructura de datos que funciona para todos (Applicative) Functor s, y desea reutilizarlo en un sentido degenerado. Es análogo a pasar const o id a funciones que funcionan con funciones arbitrarias.

Van Laarhoven lenses se definen en términos de Functors arbitrarias, y el uso Const para derivar un descriptor de acceso de campo (y el igualmente trivial Identity para derivar un actualizador de campo).

Traversable tipos, como menciones pigworker, son otro ejemplo de esto.

7

Como menciona dave4420, implementar el accesorio y el actualizador para lentes Van Laarhoven implica Const functor. Elaborar:

{-# LANGUAGE Rank2Types #-} 

import Control.Applicative 
import Control.Monad.Identity 

-- The definition of Van Laarhoven lenses: 
type Lens a b = forall f . Functor f => (b -> f b) -> (a -> f a) 

-- Getter passes the Const functor to the lens: 
get :: Lens a b -> a -> b 
get l = getConst . (l Const) 

-- Updater passes the Identity functor to the lens: 
modify :: Lens a b -> (b -> b) -> (a -> a) 
modify l f = runIdentity . l (Identity . f) 

set :: Lens a b -> b -> (a -> a) 
set l r = modify l (const r) 

-- Example: ------------------------------------------- 

data Person = Person { _name :: String, _age :: Int } 
    deriving Show 

name :: Lens Person String 
name f (Person n a) = fmap (\x -> Person x a) (f n) 

age :: Lens Person Int 
age f (Person n a) = fmap (\x -> Person n x) (f a) 

main :: IO() 
main = do 
    let john = Person "John" 34 
    print $ get age john 
    print $ set name "Pete" john