One way to generalize incrementPersonCounter
is the abstract over the modification function:
modifyPersonCounter :: (Int -> Int) -> Person -> Person
modifyPersonCounter f p = (\c -> p { counter = c}) $ f (counter p)
In fact, the general template is an abstraction, as well as the effect that we want to perform in the field:
counterLens :: forall f. Functor f => (Int -> f Int) -> (Person -> f Person)
counterLens f p = (\c -> p { counter = c }) <$> f (counter p)
For example, we may need to read the counter increment from the console or from the database (both effects IO
).
, , ( ) , :
type Lens' a b = forall f. Functor f => (b -> f b) -> (a -> f a)
, , over
, :
over :: Lens' a b -> (b -> b) -> a -> a
over l f p = runIdentity $ l (Identity . f) p
:
*Main> over counterLens (+1) (Person "foo" 40)
Person {name = "foo", counter = 41}
, "" , . Template Haskell, .
, , ? , , . , , . , ( , Haskell ), , , .
lens, microlens, . : , , .