Funktionslinsen

79

Könnte mir jemand Funktionslinsen erklären? Es ist ein überraschend schwieriges Thema für Google und ich habe keine Fortschritte gemacht. Ich weiß nur, dass sie ähnliche Get / Set-Funktionen bieten wie in OO.

Masse
quelle
7
Es gibt eine schöne Einführung in Objektive von Edward Kmett auf YouTube. Die Beispiele sind in Scala, aber es sollte nicht zu schwer sein, zu folgen.
Hammar
Ja, versucht, diese zu sehen, aber genug Zeit zu haben, während ich noch wachsam bin, ist nicht so einfach: P
Masse
2
@Jochen: Die dort beschriebenen Objektive haben nicht wirklich viel mit den Objektiven zu tun, um die es in dieser Frage geht.
sclv
3
Hier ist eine schöne Einführung mit Bildern: Objektive in Bildern .
Debjit

Antworten:

61

Ein Objektiv besteht aus zwei Funktionen, einem Getter und einem Setter:

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

Zum Beispiel könnten wir Linsen für den ersten und zweiten Teil eines Paares haben:

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)

Der wahre Komfort von Objektiven besteht darin, dass sie Folgendes zusammensetzen:

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

Und sie wandeln sich mechanisch in StateÜbergänge um:

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)
Apocalisp
quelle
Ihr komponiertes Beispiel hat nicht typecheck. GHC schließt daraus; Objektiv aa -> Objektiv aa -> Objektiv aa
Masse
Masse: Ich habe versehentlich das fund umgedreht g.
Apocalisp
Check wird immer noch nicht in a-> c eingegeben. Daraus folgt: Lens ab -> Lens aa -> Lens ab
Masse