
On Mon, Jan 13, 2014 at 09:54:55PM +0400, Dmitriy Matrosov wrote:
but if Graph has many records, for most of them these 'set' functions ('get' functions i'll have from records) will look very similar. Is there a way how i can define all of them "in one row", i.e. using some generic 'set' implementation to which i should only pass e.g. record name or smth else? I.e. so, that above myGraph will look like
.. tell(set r x) ..
Yes, you can do this with the 'lens' package. The package is big and complicated, but here's all you need to know: 0) import Control.Lens 1) Name your fields with underscores:
data Graph = Graph { _graphTitle :: String, _graphPoints :: [Int] } deriving (Show)
2) Add the line
$(makeLenses ''Graph)
after the definition of Graph (also be sure the TemplateHaskell extension is enabled) 3) Now you can use the 'view' and 'set' functions (or their infix equivalents, (^.) and (.~)), like so: .. tell (set graphTitle x) .. or tell (graphTitle .~ x) makeLenses generated a special lens called 'graphTitle' from the field name '_graphTitle'. Of course the above doesn't actually typecheck since (set graphTitle x) is a function but you need a Dual Endo, but you can easily make your own custom set function that adds the Dual Endo wrapper, etc. -Brent