Re: Better Records was Re: [Haskell-cafe] Type Directed Name Resolution
On Fri, Nov 12, 2010 at 22:48, Jonathan Geddes geddes.jonat...@gmail.com wrote: Records do leave quite a bit to be desired. But does anybody actually have a concrete alternative proposal yet? A few months ago I proposed a couple of extensions [1] on -cafe. [snip] Consider what this would do for nested updates: UpdateTripleInner :: (Inner-Inner) - MyTriplyNestedRecord - MyTriplyNestedRecord UpdateTripleInner f = \{inner1 = \{inner2 = \{inner3 = f }}} I cringe to imagine what the equivalent is in current Haskell syntax. Anyone want to try it? Not me! You can do this very conveniently already using the fclabels package: updateTrippleInner = modL (inner3 . inner2 . inner1) Here, inner1/2/3 are not record fields, but Lenses. You have to construct the lenses themselves, but this is very easy, and can be automated using Template Haskell. Other packages like data-accessor have similar functionality. Erik ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Better Records was Re: [Haskell-cafe] Type Directed Name Resolution
On 11/11/2010 11:48 PM, John Lask wrote: again quoting 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? Records do leave quite a bit to be desired. But does anybody actually have a concrete alternative proposal yet? Personally I'm not really keen on TDNR; I'd prefer records that aren't so inconvenient. But I have no idea how to design that. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Better Records was Re: [Haskell-cafe] Type Directed Name Resolution
Records do leave quite a bit to be desired. But does anybody actually have a concrete alternative proposal yet? A few months ago I proposed a couple of extensions [1] on -cafe. The jist of it is in the following: someUpdate :: MyRecord - MyRecord someUpdate myRecord = myRecord { field1 = f $ field1 myRecord , field2 = g $ field2 myRecord , field3 = h $ filed3 myRecord } becomes someUpdate :: MyRecord - MyRecord someUpdate = \{field1 = f, field2 = g, field3 = h} The two syntax changes here are: 1. '=' remains as assignment in record updates, but = is added and means 'field is transformed by', and 2. \{...} is a first-class lambda update. It's made possible by the 1 since with 1 you no longer need to reference the entire record anywhere in the update Consider what this would do for nested updates: UpdateTripleInner :: (Inner-Inner) - MyTriplyNestedRecord - MyTriplyNestedRecord UpdateTripleInner f = \{inner1 = \{inner2 = \{inner3 = f }}} I cringe to imagine what the equivalent is in current Haskell syntax. Anyone want to try it? Not me! These extensions, admittedly, don't do anything for the namespacing problem, which might be a bigger issue than awkward updates. I submit that it's a different and somewhat unrelated issue, though I'd love to see something that addresses both (all?) of the issues! --Jonathan Geddes [1] http://www.mail-archive.com/haskell-cafe@haskell.org/msg81509.html On Fri, Nov 12, 2010 at 1:29 PM, Andrew Coppin andrewcop...@btinternet.com wrote: On 11/11/2010 11:48 PM, John Lask wrote: again quoting 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? Records do leave quite a bit to be desired. But does anybody actually have a concrete alternative proposal yet? Personally I'm not really keen on TDNR; I'd prefer records that aren't so inconvenient. But I have no idea how to design that. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Better Records was Re: [Haskell-cafe] Type Directed Name Resolution
On 12 November 2010 21:48, Jonathan Geddes geddes.jonat...@gmail.com wrote: I cringe to imagine what the equivalent is in current Haskell syntax. Anyone want to try it? Not me! Perhaps not pretty - but it is regular and avoids Template Haskell an manages for the few times I have records-in-records: doubleInner3OfA :: A - A doubleInner3OfA = (\s a - s { inner1 = f1 a }) * inner1 where f1 = (\s a - s { inner2 = f2 a }) * inner2 f2 = (\s a - s { inner3 = 2 * a }) * inner3 data A = A { inner1 :: B } deriving (Eq,Show) data B = B { inner2 :: C } deriving (Eq,Show) data C = C { inner3 :: Int } deriving (Eq,Show) t1 = A (B (C 1)) demo1 = doubleInner3OfA $ t1 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Better Records was Re: [Haskell-cafe] Type Directed Name Resolution
If the outcome of this discussion is a clamour for better records instead of TDNR, then that would certainly make me happy. Regards, Malcolm well I certainly am clamouring for better records. 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. As I tried to point out in my original post, issues of name space management are orthogonal to the type system, but obviously related as the type system in Haskell is used to distinguish names. The thrust of discussion and work on the record system, in so far as Haskell has been concerned, has been at the type system level, an necessarily so: work on representing the has a relation, extensibility etc at the type level. Some relatively usable libraries have been developed that provide this support (eg HList). none of this can address my particular issue: name space management, that is, managing the scope of record labels. The type system is not the solution to all problems. Hence my proposal. I don't envisage that my issue will be addressed anytime soon, if at all. But by raising it I hope to broaden the focus of the discussion. The trouble with any rework of the current record system: which way to take it ... the design space is large what would users want ... - light weight records (c.f. ML) - first class labels (accessors and setters) - extensible records - sub-typing or in my case - better name space management perhaps given the many avenues for exploration of type system support for record systems, we could make use of existing libraries with rebind-able syntax?? again quoting 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? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Better Records was Re: [Haskell-cafe] Type Directed Name Resolution
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