András Kovács answer shows how to achieve this with RankNTypes . If you want to avoid RankNTypes , you can use ALens and cloneLens :
f :: a -> ALens' a Int -> (Int, a) fal = (newvalue, a & cloneLens l .~ newvalue) where oldvalue = a^.cloneLens l newvalue = if oldvalue == 0 then 0 else oldvalue - 1
Control.Lens.Loupe provides operators and functions that work on ALens instead of Lens .
Note that in many cases, you can also use <<%~ , which is similar to %~ , but also returns the old value or <%~ , which returns the new value:
f :: a -> LensLike' ((,) Int) a Int -> (Int, a) fal = a & l <%~ g where g oldvalue = if oldvalue == 0 then 0 else oldvalue - 1
This has the advantage that it can also work with Isos or sometimes also with Traversals (when the target type is Monoid ).
bennofs
source share