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.
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.
Antworten:
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)
f
und umgedreht g
.
Siehe die Antwort auf Frage Linsen, Fclabels, Datenzugriff - welche Bibliothek für Strukturzugriff und Mutation besser ist - es gibt eine sehr klare Erklärung zu Linsen.
In der Dokumentation zu den Data.Lenses- und fclabel- Bibliotheken finden Sie einige gute Beispiele für deren Verwendung.