[Haskell-beginners] Initialize a data type in (Writer (Endo a)) monoid
Brent Yorgey
byorgey at seas.upenn.edu
Mon Jan 13 19:07:27 UTC 2014
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
More information about the Beginners
mailing list