Monday, March 18, 2013

Function Signatures

If this is going to be a statically typed language, then that should apply to functions when they are passed as arguments to other functions.  If we are going to pass a function to something resembling Haskell's map, then the compiler should verify that the function we are passing takes two parameters, and they match the types of other arguments appropriately.

My first inclination is to do that with interfaces: Let each lambda expression that shares a particular signature implement an interface unique to that signature.  With some additional class definitions, we ought to be able to define a single set of intermediate curried states for all functions that share the same signature, since the control part exists only at the end of the curry chain.

And lastly, if we can use something like the generic type parameters in C#, we can boil down our separate definitions to one for every number of parameters, as follows:
interface ISignature<T1, T2, TReturn> {
    TReturn Value(T1 p1, T2 p2);
    ISignature<T2, TReturn> Curry(T1 p1);
}

class Curried<T1, T2, TReturn> : ISignature<T1, T2, TReturn> {
    ...
}

class MyFunction : ISignature<DateTime, int32, DateTime> {
    ...
}

Fig. 5.1: An interface representing a function signature and some matching lambda expressions as classes

I think this approach, in general, will work.  In the next post I'll attack lazy evaluation.

No comments:

Post a Comment