caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: John Prevost <prevost@maya.com>
To: Pierre Weis <Pierre.Weis@inria.fr>
Cc: Jacques Garrigue <garrigue@kurims.kyoto-u.ac.jp>, caml-list@inria.fr
Subject: Re: Syntax for label, NEW PROPOSAL
Date: 15 Mar 2000 12:04:45 -0500	[thread overview]
Message-ID: <87k8j4p3ki.fsf@isil.localdomain> (raw)
In-Reply-To: Pierre Weis's message of "Wed, 15 Mar 2000 14:58:30 +0100"

As usual, best most consistent idea is at the end.  Please forgive my
rambling.

Pierre Weis <Pierre.Weis@inria.fr> writes:

> The real problem is that fixing the code makes no good at all to its
> readability (at least that's what I would say):
> 
> # let sum l = List.fold_right fun:begin fun x acc:y -> x + y end acc:0;;
> val sum : 'a -> int list -> int = <fun>
> 
> It seems that, in the ``modern'' mode, application of higher order
> functions is now denoted by a new kind of parens opening by
> ``fun:begin fun'' and ending by ``end''. This is extremely explicit
> but also a bit heavy (in my mind).

Whoa.  You can't just use fun:(+)??  There's a new acc label that's
used for folds?  I might have argued that fun: (or an alternative
which isn't a reserved word, which I would support) isn't so bad to
type.  But with the labeled argument to the argument of the HOF, this
is too much.

As for the other semantic badness (which I actually think is syntactic
badness to some degree) let's see what we can do:

> -- syntactically identical patterns and expressions now may have
> incompatible types:
>    # let f ?style:x _ = x;;
>    val f : ?style:'a -> 'b -> 'a option = <fun>
> 
>    As a pattern on the left-hand side x has type 'a, while as an
>    expression on the right hand side it has type 'a option

I think this could be made sane by a reform of how the optional
arguments work.  There are a couple of interesting possibilities:

# let f ?style:x _ = x;;
- val f : ?style:('a option) -> 'b -> 'a option

# let f (style:x : 'a option) _ = x
- val f : style:('a option) -> 'b -> 'a option

In the first case, the type of an optional labelled argument is always
an option.  (This makes sense in the context of what I'll say about
arguments with default values below.)

In the second case, any labelled argument with an option type becomes
an optional argument.  This has the disadvantage that it's impossible
to have a required option argument.  But one might argue that this
interpretation makes sense.

The first is dirty because there are two kinds of special arguments
(optional and non-optional).  The second because it gets into the type
system.  I think the second must lose, since "knowing" that something
is an option type is complex.

> -- some expressions can be only written as arguments in an application
>    context:
>    # let f ?style:x g = ?style:x;;
>                         ^
>    Syntax error
>    # let f ?style:x g = g ?style:x;;
>    val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>

I think you have to consider this sort of thing in the context of
"application involves labelled arguments now" and "this syntax is part
of application syntax and argument pattern syntax, not expressions or
arbitrary patterns".  It is a little dirty, but survivable.  A syntax
which made it more obvious what was going on might be nice.  I might write:

# let f ?style x g = ?style x
  Syntax error (label in non-application position)
# let f ?style x g = g ?style x
- val f : ?style 'a -> ?style ('a -> 'b) -> 'b

Now, ?label is a special token that changes the meaning of
application.  To some degree, like methods on objects.  ? would "bind"
more closely than application, because it's sort of like an infix.
But like #, it's more of a special effect on the following symbol.
This is why I write:

fooobj #method val

instead of

fooobj#method val

when I use the object syntax.

> -- the simple addition of a default value to an optional argument may
>    trigger a typechecking error:
>
>    # let f ?(style:x) g = g ?style:x;;
>    val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>
>
>    # let f ?(style:x = 1) g = g ?style:x;;
>    This expression has type int but is here used with type 'a option

Okay.  This is where my thought about changing the way this works
comes in.  From the point of view of the called function, an optional
argument with a default value is not optional at all!  From the
outside, of course, it is.  But what if we did it like this:

# let f ?(style:x) g = g ?style:x;;
- val f : ?style:('a option) -> ((?style:'a option) -> 'b) -> 'b = <fun>
# let f ?(style:x = 1) g = g ?style:x;;
                    -
  This expression has type int but here is used with type 'a option
# let f (style:x = 1) g = g ?style:x;;
                                   -
  This expression has type int but here is used with type 'a option
# let f ?(style:x = Some 1) g = g ?style:x;;
- val f : ?style:('a option) -> ((?style:'a option) -> 'b) -> 'b = <fun>
# let f (style:x = Some 1) g = g ?style:x;;
- val f : style:('a option) -> ((?style:'a option) -> 'b) -> 'b = <fun>


What's going on here?  The idea is that ? forms *always* require an
option as their value, and the bound value is always an option.  When
you pass a value with:

foo (?style:x)

foo must have type:

foo : (?style:'a option) -> 'b

Note that I have both optional and non-optional argument syntax above
with default values.  Above, we see how changes effect local code in
our function.  (As expected, if we cause the type of the bound
variable to change, the function breaks.  Otherwise it doesn't.)

What happens to people outside?  Well, if we switch from a ? form to a
non-? form, we're removing the implicit optionizing of the argument.
That is:

# let f (?style:x) = x;;
- val f : ?style:('a option) -> 'a option

# let f (style:x) = x;;
- val f : style:'a -> 'a

# let f (?style:x = Some 5) = x;;
- val f : ?style:('a option) -> 'a option

# let f (style:x = 5) = x;;
- val f : ?style:int -> int

Now, what's going on here?  The ? in the type relates only to whether
the argument is required or not.  When the argument is declared with
?, this must be an option!  When it is declared without ?, it may be
anything.


Come to think of it, this doesn't work either.  It makes everything
keep working as long as you keep the external type the same--but I
just realized that telling the difference between labels that should
be "optioned" and labels that shouldn't is hard.

Okay.  One last try.

What if we drop back one and say that there is only one kind of
labeled argument, written in this way (for my sake writing this):

# let f ?style x = x;;
- val f : ?style 'a -> 'a

Okay.  So how to optional arguments work?

# let f ?style x () = x;;
- val f : ?style 'a -> unit -> 'a
# f ();;
- : '_a option = None
# f ?style (Some 27) ();;
- : int option = Some 27

What's going on here?  Well--let's extend the syntax to cover default
arguments:

# let f (?style x = 5) () = x;;
- val f : ?style int -> int
# f ();;
- : int = 5

# let f (?style x = None) () = x;;
- val f : ?style 'a option -> 'a option
# f ();;
- : '_a option = None

and again, for reference:

# let f (?style x) () = x;;
- val f : ?style 'a -> 'a
# f ();;
- : '_a option = None

So how is this happening--what's the interpretation?





Oh shoot.  This doesn't work either.  I was going to suggest that you
can always leave out a label, and that the default value will be
substituted in, or if you didn't give a default, None will be
substituted in.  But that doesn't account for the top case above.  One
possibility is that it doesn't make sense to use a non-option default
value:

# let f (?style x = 5) () = x;;
- val f : ?style int -> int
* Warning: default value is not an option

# f ();;
  f ?style None ();;
           ----
  This expression has type 'a option but is here used with type int

# f ?style 3 ();;
- : int = 3

This is consistent, but sort of weird.  It does certainly provide a
fairly simple model of what optional arguments are, though.  The only
nastiness is that you need to do extra typing for each optional value
given.  I think this is a reasonable price to pay for sanity.

# let f (?style x = Some 5) () = x;;
- val f : ?style int option -> int option
# let g (?style Some x = Some 5) () = x
  Warning: this pattern-matching is not exhaustive.
  Here is an example of a value that is not matched:
  None
- val g : ?style int option -> int = <fun>
# f ();;
- : int option = Some 5
# g ();;
- : int = 5



Of course, this is all radically different from O'Labl, so it will
never happen.

John.



  parent reply	other threads:[~2000-03-17  8:08 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-03-14 16:53 Syntax for label Don Syme
2000-03-14 18:05 ` Pierre Weis
2000-03-15  3:15 ` Syntax for label, NEW PROPOSAL Jacques Garrigue
2000-03-15  6:58   ` Christophe Raffalli
2000-03-15 21:54     ` Julian Assange
2000-03-15 11:56   ` Wolfram Kahl
2000-03-15 13:58   ` Pierre Weis
2000-03-15 15:26     ` Sven LUTHER
2000-03-17  7:44       ` Pierre Weis
2000-03-15 17:04     ` John Prevost [this message]
2000-03-17 10:11       ` Jacques Garrigue
2000-03-15 17:06     ` Markus Mottl
2000-03-15 19:11     ` Remi VANICAT
2000-03-17  8:30       ` Pierre Weis
2000-03-17 14:05         ` Jacques Garrigue
2000-03-17 16:08           ` Pierre Weis
2000-03-18 10:32           ` Syntax for label, NEW SOLUTION Christophe Raffalli
2000-03-19  2:29             ` Jacques Garrigue
2000-03-20 18:25               ` Christophe Raffalli
2000-03-22  8:37                 ` Claudio Sacerdoti Coen
2000-03-21 23:29               ` John Max Skaller
2000-03-29  8:42               ` Semantic of label: The best (only ?) solution to merge both mode Christophe Raffalli
2000-03-29  9:53                 ` Christophe Raffalli
2000-03-30  9:49                   ` John Max Skaller
2000-03-30  9:39                 ` John Max Skaller
2000-03-31  4:34                   ` Jacques Garrigue
2000-04-01  1:53                     ` John Max Skaller
2000-04-02 19:24                     ` Christophe Raffalli
2000-04-04  5:50                       ` Jacques Garrigue
2000-04-03  7:57                     ` backward compatibility Christophe Raffalli
2000-03-15 21:30     ` Syntax for label, NEW PROPOSAL John Max Skaller
2000-03-16  2:55     ` Jacques Garrigue
2000-03-17 15:13       ` Pierre Weis
2000-03-17 17:33         ` Wolfram Kahl
2000-03-18 11:59         ` Jacques Garrigue
2000-03-21 16:51       ` Pascal Brisset
2000-03-23 11:14         ` Nicolas barnier
2000-03-24  9:54           ` labels & ocaml 3 & co David Mentré
2000-03-24 12:19             ` David Mentré
2000-03-21 22:22       ` Unsigned integers? John Max Skaller
2000-03-22 16:22         ` Sven LUTHER
2000-03-23  2:08           ` Max Skaller
2000-03-23  7:50             ` Sven LUTHER
2000-03-24  2:50             ` Jacques Garrigue
2000-03-24 15:59               ` Xavier Leroy
2000-03-25  4:03               ` John Max Skaller
2000-03-24 14:50             ` Xavier Leroy
2000-03-22 17:05         ` Jean-Christophe Filliatre
2000-03-22 19:10           ` Markus Mottl
2000-03-23  2:41           ` Max Skaller
2000-03-22 19:47         ` Xavier Leroy
2000-03-23 12:55           ` John Max Skaller
2000-03-16  8:50     ` Syntax for label, NEW PROPOSAL Pascal Brisset
2000-03-17 11:15       ` Sven LUTHER
2000-03-18  0:04     ` Syntax for label, ANOTHER " Steven Thomson
2000-03-15 20:39   ` Syntax for label (and more) Xavier Leroy
2000-03-17 10:03     ` Christian RINDERKNECHT
2000-03-17 17:19       ` Christophe Raffalli
2000-03-21  1:29     ` Markus Mottl
2000-03-15 20:40 Syntax for label, NEW PROPOSAL Don Syme
2000-03-17  9:48 ` Jacques Garrigue
2000-03-17 17:34   ` Dave Mason
2000-03-18  0:26     ` Jacques Garrigue
2000-03-23 13:07       ` Sven LUTHER
2000-03-17 17:03 Don Syme
2000-03-17 19:24 ` John Prevost
2000-03-17 21:33 Damien Doligez
2000-03-18 21:07 ` Frank Atanassow
2000-03-18 22:40 ` John Prevost

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87k8j4p3ki.fsf@isil.localdomain \
    --to=prevost@maya.com \
    --cc=Pierre.Weis@inria.fr \
    --cc=caml-list@inria.fr \
    --cc=garrigue@kurims.kyoto-u.ac.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).