Isomorphism lenses

后端 未结 2 1126
暖寄归人
暖寄归人 2021-02-14 07:46

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

2条回答
  •  鱼传尺愫
    2021-02-14 08:07

    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.

提交回复
热议问题