Metaprogramming manipulates abstract code declarations so a compiler can generate additional code at compile time. It can make a codebase more expressive and flexible, but generated code is implicitly embedded and may be hard to inspect. section 2.1.2
Use it carefully when repeated structural code obscures a design. For example, generated lenses can remove accessor boilerplate for nested data while preserving concise, readable operations. section 2.1.2
Generating lenses for a record
A Person record declares private-looking fields, then makeLenses generates lenses used by getFirstName. The call expresses the desired generated interface rather than manually writing each accessor. section 2.1.2
data Person = Person { _name :: PersonName #1
, _age :: Age }
person = Person ("Jane", "Doe") 31
makeLenses ''Person #2
getFirstName :: Person -> String
getFirstName person = view (name . _1) person #3
-- getFirstName janeDoe == "Jane"
Inspect the record declaration, generation instruction, and resulting lens composition together. section 2.1.2


