I'm currently working on expanding the capabilities of my pet programming language project's type system, and have come across an interesting area where my research into other language's type systems hasn't taken me before.
As background, my language is an object-functional language with static types and partial type inference. The language will (but doesn't yet) support both of these features:
- functions whose behaviour depend on the runtime type of all of their arguments (ie multi-methods)
- union types, i.e. a value may have one of many types, all of which are transparently tracked at runtime (similar to a sum type but without needing explicit construction or declaration of which types can be used).
Given this combination, the type of a function is interesting. For example, if I have a value defined thus:
v : union (int, string) = randomInt & 1 == 0 ? 1 : "hello"
I can then apply this to any function that accepts either int or string for its first argument. This could mean a function that accepts a union type:
fn1 (p : union (int, string)) { p + 1; }
But it could also be a multi-method that is defined to accept either type:
fn2 (p : int) { "Integer: " + p; },
(p : string) { p.length }
While I could describe the types of these functions by using a union of their parameters and result, i.e. (using an appropriately extended Haskell-like notation):
fn1 :: union (int, string) -> union (int, string)
(and the same type for fn2) this loses information, i.e. the fact that fn1 maintains the type of its argument while fn2 swaps between the two types.
Has anyone seen a language that tracks function types in this way? If so, what kind of notation does it use for the combination of different argument and result types and their interactions? Is there a name for the kind of function type we're talking about? And is it worth doing, or should I just allow the information to be lost?
Another interesting thought: the function fn2 can be seen as a combination of two functions, one of type int-> string and the other string-> int. My first thought was that the function's type is a union of these, but that's obviously wrong - my current thinking is that it's actually a dual of the union type, analogous to the way a product type relates to a sum type. Any other thoughts on this? Am I on the right track? Is there a standard name for such a type?
int
,string
, andint|string
.