1 Problem description
Lenses provide uniform and compositional way to view and edit data structures.For example, one can view and edit pairs with
Similarly, there is a complete toolbox of lenses for records, the toolbox contains one lens for each record field.
Now, the problem is, are there a toolbox of lenses for algebraic data types with multiple constructors?
2 Existing solutions
2.1 Partial lenses
The data-lens library provides partial lenses which are isomorphic to
type PartialLens a b = (a -> Maybe b, a -> Maybe (b -> a))
The flollowing partial lenses are defined for lists:
headLens :: PartialLens [a] a headLens = (get, set) where get  = Nothing get (h:t) = Just h set  = Nothing set (h:t) = Just (:t)
tailLens :: PartialLens [a] [a] tailLens = (get, set) where get  = Nothing get (h:t) = Just t set  = Nothing set (h:t) = Just (h:)
2.2 Other solutions
Please help to extend the list of known solutions.
3 ADT lenses
The proposed solution, summarized:
Use one lens for each ADT type, with reversed direction.
3.1 Example: List lens
The ADT lens for lists:
listLens :: Lens (Bool, (a, [a])) [a] listLens = lens get set where get (False, _) =  get (True, (l, r)) = l: r set  (_, x) = (False, x) set (l: r) _ = (True, (l, r))
3.2 UsageSuppose that we have a state
type S = (Bool, (Int, [Int]))
We can edit the list with the following lenses:
- With the top level constructor of the list can be viewed and edited:fstLens :: Lens S Boolcorresponds toFalseandcorresponds toTrue.(:)
- With the first element of the list can be viewed and edited. Note that if the top level constructor of the list isheadLens = fstLens . sndLens :: Lens S Int, the first element can still be edited; the change will only be visible throughwhen the constructor is changed back tolistLens. (This may seem to be odd, but for certain applications this is the right behaviour.)(:)
- With the tail of the list can be viewed and edited.tailLens = sndLens . sndLens :: Lens S Int
4 Links and references
I have not seen this technique described before. Please help to extend the list of papers / blog entries, where this or similar technique is used.