(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
and implement it in a structure S such that the following makes sense:
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 )
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 )