May 26th, 2012

beartato phd

(no subject)

I chatted with Sean today for a while and he left me with a cute types puzzle. The puzzle is, assign types to the ?s in the signature
sig 
    val blank : ?
    val binop : (int * int -> int) -> ?
    val unop : (int -> int) -> ?
    val const : int -> ?
    val eval : ?
end

and implement it in a structure S such that the following makes sense:
open S
(* expression with holes: [ ] + (~[ ] + (2 * [ ])) *)
val f = eval (binop (op+) blank (binop (op+) (unop (op~) blank) (binop (op *) blank (const 2))))
val _ = print (Int.toString (f 100 2 3000)) (* prints 100 + (~2 + (2 * 3000)) = 6098 *)
val _ = print "\n"

What's going on here is f builds up an expression tree out of binary and unary operators and integer constants and blank holes, calls eval on it, and this has the type
int -> int -> int -> int
which is a curried type with three integer arguments, equal to the number of occurrences of "blank" in the definition of f.

But how can you get eval to have a type that always has one curried argument for each blank, and in fact evaluates the right expression?
Collapse )