You can get an important hint fromto solution by thinking about how to make the yin-yang puzzle work in a typed language, see this question. OCaml computes the type of yin
and yang
to be ('a -> 'a) as 'a
, which is a recursive type equal to its own function space. Such a type is precisely what it takes to implement the untyped $\lambda$-calculus in a typed language.
You can compute the CPS transform in the privacy of your mind. I do not have the time right nowHere is my version, but will come back to complete the answerwritten in Ocaml. The morale is thatTo run it, you should be ableneed to do thispass -rectypes
to Ocaml:
let callcc f k = f k ;;
let yin c = callcc (fun x -> x x) (fun k -> print_char '@'; c k) ;;
let yang c = callcc (fun x -> x x) (fun k -> print_char '*'; c k) ;;
let _ = yin yang (fun x -> x) ;;
Clearly, the let
statements are just a convenience. Without them, and with 'callcc' expanded out, we get:
(fun c -> (fun x -> x x) (fun k -> print_char '@'; c k))
(fun c -> (fun x -> x x) (fun k -> print_char '*'; c k))
(fun x -> x)
We could remove the $\lambda$print_char
statement and $\eta$-calculusreduce:
Start with:
(fun c -> (fun x -> x x) (fun k -> c k))
(fun c -> (fun x -> x x) (fun k -> c k))
(fun x -> x)
Reduce fun k -> c k
to c
:
(fun c -> (fun x -> x x) c) (fun c -> (fun x -> x x) c) (fun x -> x)
Reduce fun c -> (fun x -> x x) c
to fun x -> x x
:
(fun x -> x x) (fun x -> x x) (fun x -> x)
So the essence of the yin-yang puzzle is just self-application of self-application. How appropriate!