Lentes funcionales


80

¿Alguien podría explicarme los lentes funcionales? Es un tema sorprendentemente difícil para Google y no he progresado. Todo lo que sé es que proporcionan una funcionalidad de obtención / configuración similar a la de OO.


7
Hay una buena introducción a las lentes de Edward Kmett en YouTube. Los ejemplos están en Scala, pero no debería ser demasiado difícil de seguir.
Hammar

Sí, intenté verlos, pero tener suficiente tiempo mientras todavía estoy alerta, no es tan fácil: P
Masse

2
@Jochen: Los lentes descritos allí no tienen mucho en común con los lentes de los que trata esta pregunta.
sclv

3
Aquí hay una buena introducción usando imágenes: Lentes en imágenes .
Debjit el

Respuestas:


61

Una lente consta de dos funciones, una captadora y una fijadora:

data Lens a b = Lens { getter :: a -> b, setter :: b -> a -> a }

Por ejemplo, podríamos tener lentes para la primera y segunda parte de un par:

fstLens :: Lens (a, b) a
fstLens = Lens fst $ \x (a, b) -> (x, b)

sndLens :: Lens (a, b) b
sndLens = Lens snd $ \x (a, b) -> (a, x)

La verdadera conveniencia de las lentes es que componen:

compose :: Lens b c -> Lens a b -> Lens a c
compose f g = Lens (getter f . getter g) $
                   \c a -> setter g (setter f c (getter g a)) a

Y se convierten mecánicamente en Statetransiciones:

lensGet :: MonadState s m => Lens s a -> m a
lensGet = gets . getter

lensSet :: MonadState s m => Lens s b -> b -> m ()
lensSet f = modify . setter f

lensMod :: MonadState s m => Lens s b -> (b -> b) -> m ()
lensMod f g = modify $ setter f =<< g . getter f

(+=) :: (MonadState s m, Num b) => Lens s b -> b -> m ()
f += x = lensMod f (+ x)

Su ejemplo de redacción no se revisó a máquina. GHC infiere; Lens aa -> Lens aa -> Lens aa
Masse

Masse: accidentalmente volteé fy g.
Apocalisp

Todavía no escribe check en a-> c. Se infiere en componer :: Lens ab -> Lens aa -> Lens ab
Masse

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.