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.