Re: Proposal: FirstClassFieldUpdates

2009-08-15 Thread Jon Fairbairn
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

2009-07-28 Thread Jon Fairbairn
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

2009-07-28 Thread Henrik Nilsson

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

2009-07-28 Thread Isaac Dupree

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

2009-07-27 Thread Isaac Dupree

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