On Thu, Feb 12, 2015 at 8:08 AM, Keean Schupke <[email protected]> wrote:

> On 12 Feb 2015 15:54, "Jonathan S. Shapiro" <[email protected]> wrote:
> Primitive functions use tuples for their arity like:
>
> primitive_add_int32 :: (int32, int32) -> int32
>
> These get wrapped into an overloaded type class, but we can omit that
> detail and  have simply:
>
> (+) a b = primitive_add (a, b)
>

I think that the root of our disconnect is a little clearer now. What you
suggest above is very similar to what F# does, and it is certainly
workable. It has the very real advantage that arity is being explicitly
encoded in the tuple syntax, which is also a simplifying thing.

One effect of this in F# is that *programmers* seem to get divided into two
camps. One camp comes from the functional programming world. That camp is
comfortable with the curried application syntax, and will use it
preferentially. The other camp comes from the world of C. That camp will
also gravitate toward what is familiar, which is to say the tuple syntax.
The two groups will tend to build libraries in mutually incompatible style,
which raises a concern that the user base will ultimately bifurcate.

One purpose of the present discussion about arity-aware function types was
to see if we could satisfy the needs of both groups with a single surface
syntax.

Just incidentally, the tuple approach violates your view that types and
implementation should be kept separate. While the tuple remains a product
type here, the rationale for this design choice is that the compiler is
going to treat "function accepting tuple" as a distinct implementation
case. And note, *not* "function being *passed* a tuple. that is:

   f( : 'a -> 'b) (1, 'c')

is not called using the native calling convention merely because the
argument type is a tuple, but

  (g : ('a, 'b) -> 'c) (1, 'c')

IS called using the native convention.[*]

  [*] Another option is to decide the calling convention after
specialization,
     in which case f actually *would* get called using the native
convention.

Anyway, the purpose of the current discussion was to see if we might be
able to successfully cary arity *explicitly* on the function type without
breaking the type system. Given that we lose most general types in the
process, I'm concluding that the answer is "no", and that we will probably
need to adopt the tuple story.

I don't see any reason the compiler to not provide the curried versions
> automatically.


I'm not entirely sure what you mean by this. Do you mean that given

  def f (x, y) = ...

the compiler will automatically know what to do with an expression

  f 1

? That would be equivalent to inserting an automatic coercion, which will
play havoc with type inference.

Do you instead mean that in your example above the + method is curried
while the primitive_add function is not?

Do you perhaps mean a third thing?

 The compiler uncurrying pass knows the original primitive type (or
> imported function type) and it would be a compile error if we cannot
> sufficiently uncurry.
>
If we proceed on the assumption that uncurrying never increases allocations
(which may not be right), then uncurrying can only make things better. But
the problem here is the adoption of curried syntax in the first place. The
problem with curried syntax is that it places the programmer in the habit
of preferring an idiom that (by default) *inserts* non-obvious allocations
and then applying best-effort to get rid of them again. Both parts of that
statement are bad for systems codes.


shap
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to