Re: Proposal: FirstClassFieldUpdates
Simon Peyton-Jones simo...@microsoft.com writes: | Proposal: FirstClassFieldUpdates | | Summary: Add some syntax that makes field updates into | functions. I'm wary about occupying too much syntactic space with Haskell's named-field notation. If you had a keyword, like update { foo = bar } meaning \x. x { foo = bar } that'd get you into a new syntactic space. It'd also make the syntax too noisy to be of any interest. But braces alone are so precious that I'm not sure that record updates justify consuming them. I'm not particularly wedded to braces, it's simply that they are the syntax already used for updates, so to make updates first class that is the obvious choice. For first class updates I'd be happy with something like “foo := bar”, but then I would want the syntax of record construction to be something similar. For some reason, the use of braces in record syntax differs from all others I can think of: all the rest are x {something; something; something} and can replaced by layout. So braces (with commas) for records at all is an irregularity. On a related matter, people want to use record syntax for GADTs and existentials. For record selection and construction these are more or less fine (ie one can make a sensible spec). But record update is another matter. Haskell 98 says that record update can change the type of a record (contrary to some posts in this thread), but the specification becomes really rather tricky for GADTs and existentials. Indeed, I was going to propose that in H Prime we might consider making update *not* change the type, backing away from the current H98 story, but one that makes the spec a lot easier. But various people have been arguing in favour of the H98 story so I may have an uphill struggle! I'm coming back to this stuff rather late; I can't say I understand the interactions between GADTs, existentials and records. In the absence of those developments what I would have liked to have seen would have been a decomposition of data declarations and the resulting types into orthogonal parts. For one thing, allowing “Constr a b c” for construction and pattern matching on something that was declared as “Constr {x::A, y::B, z::C}” looks improper to me, and another is the restricted nature of Haskell’s union types (cf what I started to talk about at AngloHaskell; see http://www.cl.cam.ac.uk/~jf15/Haskell-notes/AngloHaskell2009-Not-Talk.xhtml for some notes on that) So the outline would be (forgive the poor choice of keywords here): 1. distinguishable types The type “dtype Constr T1 T2…” would correspond to a single alternative of a data declaration (dtype is just an arbitrary keyword from distinguishable type). The idea is that two dtypes only match if their (fully qualified) constructors match. 2. Symmentric unions of distinguishable types A type (dtype1 | dtype2 | …) corresponds to the alternatives of a data declaration. Note that “|” can only be used on distinguishable types (and unions of distinguishable types). So a non-record-syntax data declaration data Widget = Thing1 A | Thing2 B | … could still be valid but now be a shorthand for type Widget = dtype Thing1 A | dtype Thing2 B | … One of the benefits of this is that the type of anything can be written down without having to refer to any declarations. 3. Once that is done, we can come up with a design for records: field1:=x . field2:=y . … $ emptyRecord Now “field:=x”; is a first class function, polymorphic on all records that have “field” as a field. We might want to choose some nicer syntax for emptyRecord, (“{}” if you like), but the only other expression syntax needed is the pseudo operator “:=”, though some syntax for the types would need to be designed. “record (field1::Type1, …)” would do, with “record ()” for the empty record. There is no /need/ to use up precious braces ;-). * * * You’ll complain that this isn’t fully worked out, and as I say, I don’t know how it interacts with GADTs and other things I’m not up to date with. But as far as I remember, I could simulate all of this in Ponder’s type system, so it shouldn’t be too hard for someone au fait with the way things are currently done to specify it properly. -- Jón Fairbairn jon.fairba...@cl.cam.ac.uk ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: Proposal: FirstClassFieldUpdates
Isaac Dupree m...@isaac.cedarswampstudios.org writes: Jon Fairbairn wrote: Parenthesis around updates would make them into functions, ie ({a=1,b=2,...}) would mean the same as (\d - d{a=1,b=2,...}), but be more concise. yes it is, however field updates are occasionally slightly annoying, since they can't change something's type at all, IIRC. Say, data C nx ny = C { x :: nx, y :: ny } x_set :: nx2 - C nx1 ny - C nx2 ny --x_set x2 c = c {x = x2} --type error If that were the case, it would be a serious wart that needed to be addressed. However, implementation would be fairly straightforward as an extension is already present in ghc: let x_set x2 c = c{x=x2} :t x_set x_set :: nx - C t ny - C nx ny ;-) (or did I misunderstand you?) -- Jón Fairbairn jon.fairba...@cl.cam.ac.uk ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: Proposal: FirstClassFieldUpdates
Hi all, Jon Fairbairn jon.fairba...@cl.cam.ac.uk wrote: Isaac Dupree m...@isaac.cedarswampstudios.org wrote: yes it is, however field updates are occasionally slightly annoying, since they can't change something's type at all, IIRC. Say, data C nx ny = C { x :: nx, y :: ny } x_set :: nx2 - C nx1 ny - C nx2 ny --x_set x2 c = c {x = x2} --type error If that were the case, it would be a serious wart that needed to be addressed. However, implementation would be fairly straightforward as an extension is already present in ghc: let x_set x2 c = c{x=x2} :t x_set x_set :: nx - C t ny - C nx ny ;-) (or did I misunderstand you?) Indeed, field update can change the type, which I guess is the point Jon is making. And Isaac's example above compiles without any problems or extensions. H98 as far as I'm aware. However, there are cases where the current field update facility arguably isn't good enough, namely when there are more than one constructor, some of which do not have certain of the fields. See http://hackage.haskell.org/trac/haskell-prime/wiki/ExistingRecords for examples, in particular Polymorphic Record Update take II. As an aside, having revisited that discussion, I still think the idea of being able to do an update for constructors that do NOT have certain fields makes a lot of sense. The record wildcard extension, that was mentioned as a possible workaround, seems far less appealing and flexible. I don't even know what it would mean if it's used more than once in a scope, e.g. what about the following: f (C1 {a = 1, ..}) (C2 {b = 2, ..}) = (C1 {a = 10, ..}, C2 {b = 20, ..}) ??? Best, /Henrik -- Henrik Nilsson School of Computer Science The University of Nottingham n...@cs.nott.ac.uk This message has been checked for viruses but the contents of an attachment may still contain software viruses, which could damage your computer system: you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation. ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: Proposal: FirstClassFieldUpdates
Jon Fairbairn wrote: Isaac Dupree m...@isaac.cedarswampstudios.org writes: Jon Fairbairn wrote: Parenthesis around updates would make them into functions, ie ({a=1,b=2,...}) would mean the same as (\d - d{a=1,b=2,...}), but be more concise. yes it is, however field updates are occasionally slightly annoying, since they can't change something's type at all, IIRC. Say, data C nx ny = C { x :: nx, y :: ny } x_set :: nx2 - C nx1 ny - C nx2 ny --x_set x2 c = c {x = x2} --type error If that were the case, it would be a serious wart that needed to be addressed. However, implementation would be fairly straightforward as an extension is already present in ghc: oh maybe I got confused. (My confusion also could have been the result of a bug that was recently fixed in GHC that affected the type of some cases like that where there are multiple constructors...) -Isaac ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: Proposal: FirstClassFieldUpdates
Jon Fairbairn wrote: Parenthesis around updates would make them into functions, ie ({a=1,b=2,...}) would mean the same as (\d - d{a=1,b=2,...}), but be more concise. yes it is, however field updates are occasionally slightly annoying, since they can't change something's type at all, IIRC. Say, data C nx ny = C { x :: nx, y :: ny } x_set :: nx2 - C nx1 ny - C nx2 ny --x_set x2 c = c {x = x2} --type error --x_set x2 = ({x = x2}) --still a type error x_set x2 c = C {x = x2, y = y c} --legal Which is possibly a reason to stay away from field-update syntax on some occasions, and therefore not want it to get a more prominent place in the language if it doesn't deserve it yet. -Isaac ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime