I propose we use polish notation to code the type into the classnames. The implication will be that there is only one possible representation for one type. And the return value will always be exactly what is left when popping the argument.
//Prefix/Polish Notation
// Int->Int
abstract class $_Int_Int {
abstract apply(Int): Int;
}
//Int -> (Int -> Int)
abstract class $_Int$_Int_Int {
abstract apply(Int): $_Int_Int;
}
//(Int -> Int) -> Int
abstract class $$_Int_Int_Int {
abstract apply($_Int_Int): Int;
}
class Add() extends $_Int$_Int_Int {
apply(Int i) : $_Int_Int = {
return new AddInner(i);
}
}
class AddInner(Int i) extends $_Int_Int {
apply(Int ii) : Int = {
return i + ii;
}
}
class ApplyIncrement(Int i) extends $$_Int_Int_Int {
apply($_Int_Int f) : Int = {
return f.apply(i+1)
}
}
//(.) :: (b -> c) -> (a -> b) -> a -> c
/** Compose
$$_A_C$$_A_B$_A_C ->
$($_A_C)$($_A_B)($_A_C) ->
$_Any$_Any_Any
*/
class $$_A_C$$_A_B$_A_C extends $_Any$_Any_Any{
apply($_A_C f) : $$_A_B$_A_C;
}
class $$_A_B$_A_C extends $_Any_Any {
apply($_A_B) : $_A_C;
}
I propose we use polish notation to code the type into the classnames. The implication will be that there is only one possible representation for one type. And the return value will always be exactly what is left when popping the argument.