I would be interested in a small example of van Laarhoven\'s isomorphism lenses, applied to a data type like data BValue = BValue { π :: Float, σ :: Float, α :: Float } de
Check out Data.Label from the fclabels package, which implements lenses for record types.
To illustrate this package, let's take the following two example datatypes.
import Data.Label import Prelude hiding ((.), id) data Person = Person { _name :: String , _age :: Int , _isMale :: Bool , _place :: Place } data Place = Place { _city , _country , _continent :: String }
Both datatypes are record types with all the labels prefixed with an underscore. This underscore is an indication for our Template Haskell code to derive lenses for these fields. Deriving lenses can be done with this simple one-liner:
$(mkLabels [''Person, ''Place])
For all labels a lens will created.
Now let's look at this example. This 71 year old fellow, my neighbour called Jan, didn't mind using him as an example:
jan :: Person jan = Person "Jan" 71 True (Place "Utrecht" "The Netherlands" "Europe")
When we want to be sure Jan is really as old as he claims we can use the get function to get the age out as an integer:
hisAge :: Int hisAge = get age jan
Consider he now wants to move to Amsterdam: what better place to spend your old days. Using composition we can change the city value deep inside the structure:
moveToAmsterdam :: Person -> Person moveToAmsterdam = set (city . place) "Amsterdam"
And now:
ghci> moveToAmsterdam jan Person "Jan" 71 True (Place "Amsterdam" "The Netherlands" "Europe")
Composition is done using the (.) operator which is part of the Control.Category module. Make sure to import this module and hide the default (.), id function from the Haskell Prelude.