Greetings, tl;dr - What Haskell Records need are semantic editor combinators for free.
I know this is yet another Record proposal among many, but none of them out there strike me as being exactly what I want in Haskell. Take the following types from a contrived example. >type Salary = Integer > >data Job = Job > { title :: String > , salary :: Salary > } > >data Person = Person > { name :: String > , job :: Job > } Since I've used record syntax, I get getter/accessor functions (title, salary, name, job) for free. Now suppose I want to create an aggregate getter function: return the salary of a given person. Piece of cake, it's just function composition >getSalary :: Person -> Salary >getSalary = salary . job Done! Now suppose I want to write a setter/mutator function for the same nested field >setSalaryMessy :: Salary -> Person -> Person >setSalaryMessy newSalary person = > person { > job = (job person) { > salary = newSalary > } > } Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. Of course immutability means that the semantics of Haskell are quite different (we're creating new values here, not updating old ones) but it's still common to model change using these kinds of updates. What if along with the free getters that the compiler generates when we use record syntax, we also got semantic editor combinator (SEC) functions[0] that could be used as follows? >setSalary newSalary = job' $ salary' (const newSalary) > >giveRaise amount = job' $ salary' (+amount) > >givePercentRaise percent = job' $ salary' (*(1+percent)) For each field x, the compiler generates a function x' (the tic is mnemonic for change). These little functions aren't hard to write, but they're classic boilerplate. >job' :: (Job -> Job) -> Person -> Person >job' f person = person {job = f $ job person} >salary' :: (Salary -> Salary) -> Job -> Job >salary' f job = job { salary = f $ salary job} These type of utility functions are a dream when working with any reference type or State Monad. > modify $ givePercentRaise 0.25 The compiler could also generate polymorphic SEC functions for polymorphic fields. Further, the compiler could disallow using old-style update syntax for fields whose SEC update function is not in scope, giving us fine-grained control over access and update. On the other hand we currently have to create new functions to achieve this (exporting the getter means exporting the ability to update as well, currently). Of course this doesn't address the namespacing issues with records, but it is likely nicely orthogonal to other proposals which do. Also note that there's a package on hackage [1] that will generate SEC functions using TH. It's nice, but I prefer the style of field names used above for updaters (field' vs editField). Let me know what you think. I'll write up an official proposal if there's a bit of general interest around this. Thanks for reading, --Jonathan [0] - http://conal.net/blog/posts/semantic-editor-combinators [1] - http://hackage.haskell.org/packages/archive/sec/0.0.1/doc/html/Data-SemanticEditors.html
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe