# LGtk/ADT lenses

### From HaskellWiki

m (fix) |
m (wording) |
||

Line 3: | Line 3: | ||

Lenses provide uniform and compositional way to view and edit data structures. | Lenses provide uniform and compositional way to view and edit data structures. | ||

− | For example, one can view and edit pairs with <hask>fstLens</hask> and <hask>sndLens</hask>. | + | For example, one can view and edit pairs with <hask>fstLens</hask> and <hask>sndLens</hask>. These two lenses form a complete toolbox for editing pairs in the sense that given pairs <hask>p :: (a, b)</hask> and <hask>q :: (a, b)</hask>, by succesive get and set operations <hask>p</hask> can be changed to be equivalent to <hask>q</hask>: |

− | + | <haskell> | |

+ | q == setL fstLens (getL fstLens q) (setL sndLens (getL sndLens q) p) | ||

+ | </haskell> | ||

− | + | Similarly, there is a complete toolbox of lenses for records which toolbox contains one lens for each record field. | |

+ | |||

+ | Are there a toolbox of lenses for algebraic data types with multiple constructors? | ||

== Existing solutions == | == Existing solutions == |

## Revision as of 21:19, 7 June 2013

## Contents |

## 1 Problem description

Lenses provide uniform and compositional way to view and edit data structures.

For example, one can view and edit pairs withq == setL fstLens (getL fstLens q) (setL sndLens (getL sndLens q) p)

Similarly, there is a complete toolbox of lenses for records which toolbox contains one lens for each record field.

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:

`import Data.Lens.Common`

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 Usage

Suppose that we have a statetype 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 toFalseand[]corresponds 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 through[]when 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.

[Reddit comments]