On 12 Feb 2015 10:10, "William ML Leslie" <[email protected]>
wrote:
>
> On 12 February 2015 at 20:52, Keean Schupke <[email protected]> wrote:
>>
>>
>> On 12 Feb 2015 09:21, "William ML Leslie" <[email protected]>
wrote:
>> >
>> > f : Nat -> Nat -> Nat
>> > f x y = ...
>> >
>> > g : {X} -> (X -> Nat) -> X -> Nat
>> > g f x = f (S x)
>> >
>> > let h = (if something then f else (g f)) in ...
>> >
>> > both f and g have the same type, but different native arities.​  The
question is, what is the native arity of h?  There are two sensible
answers.  Of the usages of h that might follow, we may have a hard time
deciding which to make first-class.  When h is a local, it might even be
sensible to provide both immediately.
>>
>> Either f and g have the same type, in which case they are substitutable
for each other, or they don't. I don't get your interpretation of type.
>
>
> Ah, see this is the point.  From the perspective of the language user,
you may remain blissfully aware that f and (g f​) have different native
arities.  They are completely substitutable.
>
> As a compiler, you will do your best to avoid any unnecessary thunking.
You're going to emit calls to a statically-determined f as two-argument
calls, or you're going to wrap f in a function that performs currying,
where it's underapplied.  And you're going to emit two call instructions
whenever you see (g f) called - one to call g, and one to call the result.

You can have an uncurrying pass in the compiler. I would define the
primitives with the native arity like this:

primitive_add :: (Int, Int) -> Int.

I would define + as a type class

(+) :: a -> a -> a

And I would let the uncurrying pass try and get both arguments for + by AST
transformation.

If you cannot get both arguments in the same place due to a module
boundary, then you have to think it anyway.

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

Reply via email to