> This motivated my original reply this post. The trouble is, what > constitutes better records? There are as many views as users of Haskell, I > bet. > > My main motivation is: > > As mentioned in my original post: better name space management. > > Surprisingly enough, I find the current record system is quite usable, bar > one feature. My particular use case: commercial applications make heavy use > of records (in connection with relational databases) and name clashes are > inevitable.
I too would like better records, and I too find them usable if not ideal in their current form. They wind up being doubly qualified, e.g. 'State.state_blocks st' and can be quite verbose. Consider an extreme case: set_track_width view_id width = do track_views <- modify_at "set_track_width" (Block.view_tracks view) tracknum $ \tview -> tview { Block.track_view_width = width } update_view view_id (view { Block.view_tracks = track_views }) update_view view_id view = modify $ \st -> st { state_views = Map.adjust (const view) view_id (state_views st) } What I am actually *doing* here, is: state.get_view(view_id).tracks[tracknum].width := width Part of the difference is that updating data is fundamentally more idiomatic in an imperative language, and it's true this is a rare example (modify_at updates a list at an index, ignore that :P). But the fact is that the difference between what I write and what I mean is reaching almost comical java-like levels. 'modify $ \st -> st { State.state_x = f (State.state_x st) }' is quite common, and modifying two levels deep also happens (which requires an auxiliary function to be readable). And the 'f' is buried in the middle of a bunch of boilerplate. > - light weight records (c.f. ML) I actually don't feel a lot of need for this... if I want a short-lived data structure I just use a tuple. I use records when they are being passed through multiple functions, and at that point I'm probably going to at least a type synonym, and then we're back to heavy-weight, right? The only place I can think of where light-weight records would be handy is simulating keyword args... but even then it seems hardly a burden to declare a datatype for it, and it gives you a place to put documentation. Any other uses out there? > - first class labels (accessors and setters) I would love this. I don't even think accessors is really the problem, they compose nicely as just functions even if they are a little wordy. It's update that's the killer. The reason I say it's bearable even though it can be quite verbose is that update (at least in my programs) is uncommon enough that I can factor all common updates into functions and then just call those. > - extensible records > - sub-typing Unlike the above things which make it more convenient to write the same code, it sounds like these things would actually let you write new kinds of code. However, I don't really feel like I'm missing that. Maybe it's a "blub" problem? Are there some examples of cool things you could do with either of the above that you can't do (conveniently) without? In fact, given that updates seem to be the only thing I care about, maybe I'd be made almost as happy by a functional refs library. There are several competing implementations on hackage but AFAIK none are considered universal and standard (none are in HP, for instance). > http://research.microsoft.com/en-us/um/people/simonpj/Haskell/records.html > > "Haskell lacks a serious record system. (The existing mechanism for named > fields in data types was always seen as a stop-gap measure.)" > > isn't it about time this changed? I sure think so :) _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe