Browse thread
Re: [Caml-list] Future of labels
-
Yaron M. Minsky
-
Jacques Garrigue
-
Judicael Courant
- Markus Mottl
- kahl@h...
- Chris Hecker
-
Judicael Courant
-
Jacques Garrigue
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Jacques Garrigue <garrigue@k...> |
| Subject: | Re: [Caml-list] Future of labels, and ideas for library labelling |
Hi Patrick,
This is only a point by point answer.
On labels vs. extensible records:
> > I'm not really convinced of that. SML for instance has structural
> > records, and uses them in its basis library. You can look at the result
> > for yourself. For me it's only half the way.
[...]
> I think that we're in agreement here. Structural records like SML is a
> start, but light-weight extensible records would address most of these
> issues.
>
> - Labeled arguments are included in a record, and unlabelled arguments
> are outside of the record. And since they are light-weight, there is no
> need to declare a type definition for the record.
That's exactly what I was pointing as a weaker form of commutation:
labeled arguments commute between themselves, but they do not commute
with non-labeled arguments.
> - Labels and currying do give a nicer syntax. On the other hand, not
> having good support for records is a detriment to the syntax. Most
> programmers coming to Caml will have an expectation that fields can belong
> to more than one record. Luckily, labelled arguments removes at least one
> reason for light-weight records.
I know the lack of light-weight records is a pain, but we have already
two record-like structures in OCaml, and tuples. Predefined records
have their advantages, so this would mean adding yet another
structure. This may happen someday, but I'm not all that
enthusiastic.
> - Optional arguments can be addressed by having a value which
> contains the default arguments which is modified by a record update
> syntax.
This handles only default arguments, optional arguments are more
powerful since their value may be computed at call time.
On proper labellings:
> > I have also eta-expanded more than necessary, to make the code more
> > readable.
> > We can write something shorter if we use labels as they were in ocaml
> > 2.99, before their trimming:
> > List.fold_left lists ~acc:IntSet.empty
> > ~f:(List.fold_left ~f:(fun ~acc item -> IntSet.add acc ~item))
> > Now, which is the more readable program, this one or yours.
>
> Hmm... hard to say. Using this API, I would wonder why isn't there a label
> for the list? It would be much simpler if every argument to a function had
> to have a label. I know this presents its own problems, but it adds to
> the things one must remember for coding.
I think this is explained in the tutorial: you should not label the
object of the operation. Normally one learns that in elementary
school, but forgets it soon after, so it can be a bit difficult.
Requires some practice before it comes out naturally.
> Regarding Haskell, what you say is surprising since I would classify
> a common use of monadic binding as a folding function. For the operator
> (>>=) which has type
>
> (>>=) :: m a -> (a -> m b) -> m b
>
> if a and b are the same type than it is a folding over computation state.
> This is certainly a common use in real programs.
I was only talking of list folding functions.
Labels are not the only way to improve readability. Infix operators
can also help.
On type errors in label mode:
> Forgetting to use the label in commuting mode can lead to incredible
> cryptic error messages.
The situation has improved a bit with 3.01.
Give it a try to see the difference. This is not perfect yet, but if
you see something clearly wrong you can send a bug report.
> As discussed above, I like to use a variant of
> list folding that gets the arugments in the "right" order and is
> tail-recursive. I tried adding labels to the arguments to see what would
> happen when they were omitted. The result was pretty surprising:
>
> val listFold : f:('a -> 'b -> 'b) -> l:'a list -> acc:'b -> 'b
>
> let cons x l = x :: l
>
> listFold cons (listFold cons [5;4;3] []) [];;
>
> While this is a contrived example to reverse a list twice, not including
> the labels gave this impressive type back from the compiler:
[monstruous type]
This problem is specific to functions returning a polymorphic type:
if your arguments match none of the labels in the function type, they
will be seen as arguments to the result of the function, producing a
huge type by unification.
If you had tried on an instanciated typed, you would have got a more
reasonable answer.
# let rec listFold ~f ~l ~(acc : int) =
match l with [] -> acc
| x :: l -> listFold ~f ~l ~acc:(f x acc);;
val listFold : f:('a -> int -> int) -> l:'a list -> acc:int -> int = <fun>
# let cons x l = x :: l;;
val cons : 'a -> 'a list -> 'a list = <fun>
# listFold cons (listFold cons [5;4;3] []) [];;
Expecting function has type
f:('a -> int -> int) -> l:'a list -> acc:int -> int
This argument cannot be applied without label
When there is enough information, one can produce accurate error
messages.
> I think this is more than enough to frighten me from using commuting label
> mode. The classic mode seems to give more sensible error messages.
In practice, I do not bump into this kind of errors very often.
In real programs, functions returning a polymorphic variable as result
are not so frequent.
> Another language that I'm very familiar with that has labelled arguments
> (in some sense) is Verilog. Instantiation by named connection is
> really crucial to using the language safely. Some observations though:
>
> 1) There are no structures in the language, so some need of labelling is
> needed.
Indeed, you will fell more directly need for labels in dynamically
typed languages.
But, while this may be true that labels are less needed from the
point-of-view of type safety, for documentation the need is identical.
Particularly in ML you don't write type annotations, and it is often
hard to follow the role of a variable in a program. Ocamlbrowser can
give you this information, but this does not replace information about
the role of an argument, which appears to be most needed when reading
a program.
> 2) There is no partial application which makes it easier to give
> intelligent error messages.
But partial application makes commutation more interesting :-)
Thanks for all these good points.
Jacques
-------------------
To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr