Функціональні лінзи


80

Хтось може пояснити мені функціональні лінзи? Це напрочуд важка тема для гуглу, і я не просунувся. Мені відомо лише те, що вони надають подібну функціональність get / set, ніж у OO.


7
На YouTube є приємний вступ до лінз Едварда Кметта. Приклади наведені в Scala, але наслідувати це не повинно бути надто важко.
Хаммар

Так, намагався спостерігати за цими, але мати достатньо часу, поки я все ще пильний, не так просто: P
Masse

2
@Jochen: Описані там лінзи насправді не мають багато спільного з лінзами, про які йдеться в цьому питанні.
sclv

3
Ось приємне введення з використанням малюнків: Лінзи у малюнках .
Debjit

Відповіді:


61

Об'єктив складається з двох функцій - геттера та сеттера:

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

Наприклад, ми можемо мати лінзи для першої та другої частин пари:

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)

Справжня зручність лінз полягає в тому, що вони складають:

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

І вони механічно перетворюються на Stateпереходи:

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)

Ваш приклад складання не перевірив тип. Висновки GHC; Lens aa -> Lens aa -> Lens aa
Masse

Массе: Я випадково перевернув fі g.
Апокалісп

Він все ще не вводить перевірку в a-> c. Він випливає: Lens ab -> Lens aa -> Lens ab
Masse

13

Див. Відповідь на питання лінз, фклабелів, доступу до даних - яка бібліотека для доступу до структури та мутації є кращою - вона має дуже чітке пояснення щодо лінз.

Крім того, документація для бібліотек Data.Lenses та fclabel наводить кілька хороших прикладів їх використання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.