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
