[Haskell-cafe] What Haskell Records Need

Erik Hesselink hesselink at gmail.com
Thu Aug 2 10:25:20 CEST 2012


Isn't this exactly the problem solved by all the lens packages?
Current popular ones are fclabels [0] and data-lens [1].

[0] http://hackage.haskell.org/package/fclabels
[1] http://hackage.haskell.org/package/data-lens

On Thu, Aug 2, 2012 at 7:34 AM, Jonathan Geddes
<geddes.jonathan at gmail.com> wrote:
> 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 at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>



More information about the Haskell-Cafe mailing list