Lambda the Ultimate

inactiveTopic Concepts: Design choices for template argument checking
started 12/24/2003; 7:23:08 AM - last post 1/18/2004; 10:31:33 PM
Ehud Lamm - Concepts: Design choices for template argument checking  blueArrow
12/24/2003; 7:23:08 AM (reads: 7092, responses: 12)
Concepts: Design choices for template argument checking
An amusing language design exercise from Stroustrup.

As we all know (?) Ada gneric units provide a clean, type-system aware, mechanism for specifying the properties of arguments to generic units (i.e, templates).

The cool thing about Stroustrup's proposal is the idea of adding support for run-time semantics and invariant checking. This would be more powerful than what you have in Ada today, but like the related notion of DbC, many have doubts whether this is really worth the hassle. Notice that most of these properties are up to the programmer, and by using a well-defined interface (or concept, or class or whatever) he assumes the responisbility for maintaining them. Exaclty like saying that something is a Monad.

I have to check but it seems the Ada generics coupled with my DbC proposal for Ada provide almost the rquired support for arugment checking (though, obviously, not for unique C++ features like template specialization and automatic instantiation).

A related note is here.
Posted to general by Ehud Lamm on 12/24/03; 7:25:47 AM

Bart van der Werf (Bluelive) - Re: Concepts: Design choices for template argument checking  blueArrow
12/24/2003; 8:47:06 AM (reads: 483, responses: 1)
I dislike the idea of concepts, i believe it just makes the error messages clearer when compiling templates in c++ but doesnt provide any clear type related constraints, only use related.

Ehud Lamm - Re: Concepts: Design choices for template argument checking  blueArrow
12/24/2003; 8:48:53 AM (reads: 487, responses: 0)
but doesnt provide any clear type related constraints, only use related.

I am not sure I understand. Can you elaborate?

Bart van der Werf (Bluelive) - Re: Concepts: Design choices for template argument checking  blueArrow
12/24/2003; 10:04:14 AM (reads: 472, responses: 1)
concept Element(e1,e2) { bool b = e1<e2; // Elements can be compared using < swap(e1,e2); // Elements can be swapped }; template concept Element(L,R)

Is used as a proposed example of a concept, with two constraints. it says nothing about the types of e1 and e2 just that both method calls should make sense for them. So this constraint is only realted to use of e1 and e2 in such statements.

Ehud Lamm - Re: Concepts: Design choices for template argument checking  blueArrow
12/24/2003; 10:48:05 AM (reads: 472, responses: 0)
Sure. The whole point is that they try to make c++ templates as untyped as possible. I find this strange, but it is a documented design goal...

Albert Y. C. Lai - Re: Concepts: Design choices for template argument checking  blueArrow
12/24/2003; 1:57:52 PM (reads: 438, responses: 1)
On the scholarship of this and companion writeups: All ideas have equivalences in known type theory, but the authors fail to acknowledge them. For example, towards the end of N1510, Stroustrup confesses that use-patterns are equivalent to type signatures with placeholders; this is covered by some sort of existential types or higher-rank polymorphism, if I know type theory correctly (if not, I still believe there is a close relation). Worse, the authors make uneducated and outdated FUD remarks on static types and type theories, e.g., "The C++ templates are fundamentally more abstract and flexible than type-based approaches (with its inspiration in math rather than in type theory)." This is very bad scholarship. If the authors instead acknowledged the foundation laid by type theory and then went on to say "but look at my streamlined syntax as use-patterns; now programmers will actually love to learn and use it!", that would actually demonstrate the true ingenuity of the authors and invite more collaboration rather than flame wars.

On the matter of making progress: But thank God, Stroustrup finally wakes up and smells the coffee!

Also kudos to Stepanov for convincing Stroustrup to get his acts together.

Ehud Lamm - Re: Concepts: Design choices for template argument checking  blueArrow
12/24/2003; 2:09:55 PM (reads: 443, responses: 0)
I had a similar reaction. But then I decided that language design notes such as this one are not really attempts at scholarship, so perhaps it's not fair to hold them up to this standard.

You know, someone may know about high order types etc. etc. and decide to produce a streamlined design note.

But I agree: One shouldn't confuse this kind of documents with research papers.

Dan Shappir - Re: Concepts: Design choices for template argument checking  blueArrow
12/25/2003; 12:44:38 PM (reads: 388, responses: 0)
Having just finished writing a small C++ library that makes extensive use of generics and STL, I can readily appreciate the sentiments expressed in this document. For example, the uniform function call syntax.

Currently, if you want to use functional combinators, e.g. those defined in the <functional> standard header, you must define your functions as function objects. Standard functions just won't work. This is because the combinators must have access to the types of function arguments, and you must explicitly provide such access using typedefs such as argument_type. As a result, you can't use all the standard functions, instead you must wrap them as objects (that define these typedefs). If you do want to use one of the function objects as a function, the syntax becomes very weird:

foo()(3);

All of this is very annoying since the compiler obviously has access to all the required information.

John Skaller - Re: Concepts: Design choices for template argument checking  blueArrow
12/27/2003; 3:34:24 AM (reads: 316, responses: 0)
Albert Y.C.Lai wrote" "All ideas have equivalences in known type theory, but the authors fail to acknowledge them."

.. Stroustrup doesn't know any type theory.

See my notes on the generic programming comparison paper.

This proposal is very weak: its type orientation is akin to object orientation and flawed by the same covariance problem. The correct way to handle this kind of thing is well known and used in SML and Ocaml via the module system.

Stroustrup has to resort to inheritance to handle two types as required by the very concept the proposal is designed to support -- iterators. It is clear the proposal, by attributing properties to individual types, cannot work properly: iterators, like vector spaces, are characterised by TWO types:

vector space: scalar type S, vector type V iterators: value type V, iterator type I

and associated functions with axioms .. which are constraints on the functions.

[From the example:]

"bool b = e1<e2;"

All this does is tell you the programmer was too lazy to pass the comparison function required. This is not a type constraint, nor is it an axiom, but a hack to compensate for the way templates are instantiated in pass two using Argument Dependent Lookup which in turn is a hack because there is no module system to pass bundles of arguments...

.. of course in C++ there really is a convenient vehicle for a module system -- classes -- and that should have been used instead I think. ** Classes can contain typedefs to several types, and static functions, and so can emulate modules.

Dan Shappir - Re: Concepts: Design choices for template argument checking  blueArrow
12/27/2003; 1:11:14 PM (reads: 283, responses: 0)
Another item I found interesting in this document is the Uniform call syntax. This reflects the impedance mismatch between FP and OOP I experienced during the development of BeyondJS. Consider, the following example (using JavaScript syntax, but should be fairly obvious):

function x() { ... }
x(); // Invokes the function
var y = x;
y(); // Invokes the same function

Using x() and y() is exactly the same. OTOH consider a scenario where x is a method and an object z:

z.x(); // Invokes method x for the instance z
var y = z.x;
y(); // Invokes method as a function, in JS this is null

The problem here is that y is assigned the value of the property, not the instance/property pair. You might say that the delegate construct in .NET was invented to deal with this issue. Obviously, we could envision a change to the PL spec so that y is assigned the instance/property pair, but then what would should happen in this case:

a.b = z.x;
a.b();

Would the invocation of the method be for the instance a or z?

One place where the problem was especially pertinent was list comprehensions. Consider a list of objects:

os.for_each(f); // invoke f on every object in os

How would I invoke a method on every object? If I write:

os.for_each(a.b);

it would invoke the function referenced by b without the instance a. Also, what should I do if I wanted to invoke a method for each object in the sequence?

The solution we used in BeyondJS is the Function.from function. It takes an object reference and a method reference and returns a function that invokes the method on that instance, e.g.:

var y = Function.from(z, z.x);
y(); // calls z.x()

You can also write it as:

var y = Function.from(z, "x");

either way, it feels like a bit of a hack.

Stroustrup's solution, when coupled with something like binder1st would address this issue, OTOH it could also likely break lots of existing code.

Oh yes, obviously this would be a none issue if we just went with dynamic dispatch instead of methods in the first place. You can even say that the new call syntax is a dynamic dispatch limited to the first arg.

Ehud Lamm - Re: Concepts: Design choices for template argument checking  blueArrow
1/10/2004; 3:13:58 PM (reads: 177, responses: 0)
Related (on Wiki).

Christophe de Dinechin - Re: Concepts: Design choices for template argument checking  blueArrow
1/18/2004; 10:22:50 PM (reads: 104, responses: 0)
I sent e-mail to Stroustrup as early as 2001 to discuss that functionality. Back then, he dismissed it as something you could implement with extra template arguments :-) I'm glad he now believes something is required, but I still believe he's missing a good half of my proposal. The proposal would be much more solid if

1/ it was based on templates. In XL, I use generic types without arguments, but with validation to represent concepts

2/ It was combined with the ability to declare "true" generic type, that make functions that use them generic automatically.

I'll probably write to him to point that out.

See http://cvs.sourceforge.net/viewcvs.py/mozart-dev/mozart/xl/TESTS/instantiation/minimax_vararg_generics.xl?rev=1.7&view=markup for an example of what you get once you have these capabilities. In the example, you declare a "concept" (to use Bjarne's terminology) named "ordered". It's not because you fail to pass a less-than, as someone else suggested, because that assumes an Ada-like model of explicit instantiation, where something like the STL cannot be constructed.