
On Wed, Feb 8, 2012 at 2:47 PM, Malcolm Wallace
On 8/02/2012, at 14:16, Steve Horne
wrote: I haven't given a lot of thought to updates.
I very much fail to see the point of replacing prefix function application with postfix dots, merely for field selection. There are already some imperfect, but adequate, solutions to the problem of global uniqueness of field names. But you now have mentioned what is really bothering me about this discussion: record updates are simply the most painful and least beautiful part of the Haskell syntax. Their verbosity is astonishing compared to the careful tenseness of every other language construct. If we could spend some effort on designing a decent notation for field updates, I think it would be altogether more likely to garner support than fiddling with dots.
It's already possible, here's what I've been experimenting with, using fclabels: import Data.Label -- | Compose lenses. (#) :: (a :-> b) -> (b :-> c) -> (a :-> c) (#) = flip (.) infixr 9 # -- | Get: @bval = a#b $# record@ ($#) :: (f :-> a) -> f -> a ($#) = get infixr 1 $# -- | Set: @a#b =# 42 record@ (=#) :: (f :-> a) -> a -> f -> f (=#) = set infix 1 =# Before: setTempo :: Y -> Config -> Config setTempo y config = config { Config.deflt = (Config.deflt config) { Config.tempo = y } } After: setTempo :: Config -> Config setTempo y = Config.deflt#Config.tempo =# y I haven't fully integrated this into my project because there are a lot of labels to convert, but it's promising so far. As far as I'm concerned, the thing to get rid of is the noisy module qualification, which was what my suggestion was aimed at. Then we'd have '#deflt . #tempo =# y', which is pretty concise, if full of #s. Of course some way to resolve 'deflt' and 'tempo' without ugly # markers would be nicer, but I think that would have to be typeclass overloading, which would still require explicit imports for all those label names. They'd also be uncontrollably global, which wouldn't let you use them inside the module but not export. So I'm starting to think that in the absence of changes to typeclasses themselves, a typeclass-using solution is never going to be satisfactory. I agree WRT updates, btw. I don't mind the existing record access very much. It's noisy (I prefix record fields too, so it's even worse: Config.default_tempo . Config.config_default), but it composes, so it just means a few more wrapped lines when they don't fit in 80 columns. The non-composing non-abstract updates are what bug me, and make me scatter about tons of 'modifyThis' functions, both for composability and to protect from field renames. I hope I can fix it with lenses, but it's a bit of a hassle trying to retrofit them onto something large.