Koen,
> If a language has the property that in one place, one can
> use a "let" block to define polymorphic bindings, and in
> another place one can only use it for monomorphic bindings,
> then I think that is bad language design.
I don't think that's a very accurate description. The "let" in "do"
is a bit of a different beast from the usual "let..in" construct.
For a start, it doesn't have an "in" keyword. This is not a trivial
point: "let"s are guaranteed to introduce polymorphism only
within the block introduced by "in". Uses of variables (functions)
bound by a "let" block are a priori monomorphic within the rest of that
block. In pactice, of course, the strongly-connected-components pass
will reconfigure big let-blocks into many separate blocks, and so
increase the amount of polymorphism. In a "do" block, however, it's
a lot harder to do the reconfiguration, so we would be stuck with
the by-default monomorphic behavior. (The current use of "let" in
"do" does some simplistic reconfiguration -- introducing an "in"
keyword to obtain polymorphism -- which does not work in the recursive
case).
> On the other hand, recursive do-notation is obviously is a
> great feature that many (at least I) have been wanting for
> some time now. If that feature implies monomorphic let
> bindings in do-notation, then there is clearly a trade-off
> to make. But don't use the argument "nobody is using this
> feature" to make the language design less consistent.
The argument is really to make the design *simpler* because
nobody is using the feature. The consistency or otherwise is
an artifact of the "let" keyword being asked to do double duty,
and that's the point at which we need to ask about consistency.
John.