Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to combine lenses (not compose)

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)

like image 836
mb14 Avatar asked Jun 23 '15 12:06

mb14


1 Answers

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.

like image 194
Aadit M Shah Avatar answered Oct 14 '22 09:10

Aadit M Shah