How to combine lenses (not compose)

648 views Asked by At

In haskell without lenses I can do things like :

data Item = Item { quantity :: Double, price ::Double }

cost :: Item -> Double
cost = (*) <$> quantity <*> price

If I use lenses instead how can I do the equivalent ? The best I can do is

cost = to $ (*) <$> (^. quantity) <*> (^. price)

Is there a better way ? (of course I want a getter or equivalent)

1

There are 1 answers

1
Aadit M Shah On

It just occurred to me that you don't need any special syntax to combine lenses. If you are creating lenses using Template Haskell (which you should be doing) then you already have primitive getters for each field, preceded by an underscore.

Hence, you could use the primitive getters to create your phantom cost getter as follows:

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data Item = Item { _quantity :: Double
                 , _price    :: Double
                 }

$(makeLenses ''Item)

cost :: Getter Item Double
cost = to $ (*) <$> _quantity <*> _price

item :: Item
item = Item { _quantity = 2, _price = 5.0 }

main :: IO ()
main = print $ view cost item

However, if you don't have access to the primitive getters then you could define cost as:

cost :: Getter Item Double
cost = to $ (*) <$> view quantity <*> view price

Your fingers don't need to move too far away from the home row in order to type out view.