Callcc_efun( k => e) works as follows: We capture the current
continuation (i.e., stack) which is expecting us to return a t
to it. We then bind the stack to the variable k as a Cont_tt
value, and continue to produce the value specified by e. One way
to think of callcc is that it captures a point in time in the
computation, and gives that point a name (k) so that we can jump
back to that point in time in the future.

Throw_ekv invokes the continuation k by "returning" the value
v to it. It throws away the current context (i.e., stack). So
for instance, if we have: 1 + throwk 3 then the context is
1 + _ which gets ignored.

We also need to specify the type of answers for a program -- this
is because a continuation is going to capture the entire context
up to the end of the program, so we know the continuation will return
a valueof ans type.

The V definition gives a value interpretation of types as Coq types.
As expected, Unit_t and Void_t map to unit and void respectively.
A Cont_tt becomes a function from t values to ans, where ans
is the answer type of the whole program. Finally, a function type
Arrow_tt1t2 is interpreted as a function from t1 to a function
which when given a contt2 (i.e., V[t2] -> ans) returns an ans.
So unwinding the definitions:
V (Arrow_tt1t2) = Vt1 -> (Vt2 -> ans) -> ans
Notice that I've packaged up the translation into a monad of sorts.
It's just that for this monad MA = contA -> ans = (A -> ans) -> ans
and the return and bind for this monad are as below.

The denotational semantis of expressions. Given an expression e such that
G |- e : t, and an environment in the value interpretation of G, we return
a Ct computation. That is, we return a function of type (Vt -> ans) -> ans.