2011-11-29 12 views
74

Czy ktoś mógłby wyjaśnić mi soczewki funkcjonalne? Jest to zadziwiająco trudny temat dla google i nie zrobiłem żadnego postępu. Wiem tylko, że zapewniają podobną funkcjonalność get/set niż w OO.Funkcjonalne soczewki

+7

Jest [miłym wstępem do soczewek] (http://www.youtube.com/watch?v=efv0SQNde5Q) przez Edwarda Kmett na YouTube. Przykłady są w Scali, ale nie powinno to być zbyt trudne do naśladowania. – hammar

+0

Yup, próbowałem to obejrzeć, ale mając wystarczająco dużo czasu, gdy jestem nadal czujny, nie jest tak łatwo: P – Masse

+2

@Jochen: Obiektywy tam opisane nie mają wiele wspólnego z soczewkami, o które chodzi. – sclv

Odpowiedz

56

soczewka składa się z dwóch elementów, getter i ustawiających:

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

Na przykład, może to mieć szkła dla pierwszej i drugiej części pary:

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) 

Rzeczywisty wygoda soczewek polega na tym, że komponują się one:

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 

I mechanicznie przekształcają się w State przejścia:

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) 
+0

Twój przykład komponowania nie sprawdził poprawności. Wskaźniki GHC; Obiektyw a -> Obiektyw a -> Obiektyw a a – Masse

+0

Masse: Przypadkowo przerzuciłem 'f' i' g'. – Apocalisp

+0

To nadal nie powoduje sprawdzenia w a-> c. Podaje się do komponowania :: Lens a b -> Lens a a -> Lens a b – Masse

Powiązane problemy