Here's another puzzle:
Is it possible in OCaml to define a variable-argument function? For
example, can one define a function f and values a and z such
that the following assertions hold:
assert (f z = 0); assert (f a z = 1); assert (f a a z = 2); assert (f a a a z = 3); ...
Once you've got that, how about generalizing it to a variable-argument
sum, i.e. define f, a, and z such that:
assert (f (a i1) (a i2) ... (a ik) z = i1 + i2 + ... + ik);
Or, if you want to eliminate the parens, define an f, a, and z
such that:
assert (f a i1 a i2 ... a ik z = i1 + i2 + ... + ik);
Comments
Continuation Passing Style
This is very Similar to a typesafe printf solution I've seen.
Continuations are crazy powerful!
nice puzzle
For the first one:
For the second and third one only a changes:
This works with or without parenthesis.
Good clean fun
I'm enjoying the puzzles! I'm no stranger to Church numerals so this wasn't a major challenge, but no matter how many times I code CN's it always feels like magic when they work. Also, version 3 is a neat trick that I wasn't expecting. :-)
First part
My solution is the same as the one at the bottom of this page, but here is some intuition. The way I looked at this was to think about "f", "f a" and "(f a) a" as being values Zero, One and Two such that Zero z = 0, One z = 1, Two z = 2, etc. Say that Zero, One and Two all have some type Num; the idea is that each represents the corresponding integer, applying "a" to a Num produces the representation of the next integer, and applying "z" to a Num produces the actual integer to which it corresponds.
One way of representing integers using functions is to use values of type 'a -> ('a -> 'a) -> 'a (the intuition being that given such a value, you supply a base case and an iterator, and the iterator is iterated correspondingly many times starting from the base). That doesn't quite work here; instead an alternative representation seems to be needed, where the representation actually holds the integer itself.
Letting the type Num be (int -> 'a) -> 'a, we can define f (aka Zero) to be
Thanks for trying out the puzzle.
It seems we all have the same solution :-). One thing I hadn't noticed until Milan pointed it out was the the solutions to puzzles two and three are the same. It only works becaus the operation is commutative. For a case where it won't work, consider defining
f,a,zsuch that:The solutions with and without parentheses require different
a's.As for the original problem, the most surprising part to me is that the types work out. Here's some code that helps me understand why.