```2020-05-20: Fixed-point operators from recursive types I     rak
================================================================

I was reading Marcelo Fiore's PhD thesis this afternoon  and
came across the following remark:

"In the sequel recursion at the level of programs is not
considered primitive, instead our viewpoint is that it
arises from recursion at the level of types."

I've heard many times over the years that you can do this, but I
never sat down and worked out how to encode fixed point
operators using recursive types. So here it goes.

----------------
- The language -
----------------

Assume we have a language containing the following rule defining
a fixed-point operator:

G, x : t |- e : t
-------------------- (fix)
G |- fix(x.e) : t

where operationally,

---------------------------------- .
fix(x.e)  ~~>  [fix(x.e) / x] e

Also suppose that our language has isorecursive types  given
by:

G |- e : pa.t
---------------------------- (unfold)
G |- unfold e : [pa.t/a]t

G |- e : [pa.t/a]t
---------------------------- (fold)
G |- fold e : pa.t

with dynamics

---------------- ,
fold(v) value

------------------------ ,
unfold(fold(e)) ~~> e

and

e ~~> e'
--------------------------- .
unfold(e) ~~> unfold(e')

We also assume abstraction / application:

G, x : t |- e : t'
---------------------- (abs)
G |- \x.e : t -> t'

G |- e : t -> t'       G |- e' : t
------------------------------------- (app)
G |- ee' : t'

with a call-by-value (or CBN if you want) dynamics:

------------- ,
\x.e value

v value
--------------------- ,
(\x.e)v ~~> [v/x]e

v value     e ~~> f
---------------------- ,
ve ~~> vf

e ~~> f
------------ .
eg ~~> fg

----------------
- The encoding -
----------------

We can encode fix(x.e) as

f(fold(f))

where

f = \y.[(unfold(y))y/x]e.

First, this is well-typed:

------------------------------- (var)
y : pa.a -> t |- y : pa.a -> t
--------------------------------------------- (unfold)  ------------------------------ (var)
y : pa.a -> t |- unfold(y) : (pa.a -> t) -> t         y : pa.a -> t |- y : pa.a -> t
-------------------------------------------------------------------------------------- (app)
y : pa.a -> t |- (unfold(y))y : t

so using substitution / cut we get

G, x : t |- e : t
-------------------------------------------- (subst)
G, y : pa.a -> t |- [(unfold(y))y/x]e : t
----------------------------------------------- (abs)
G |- \y.[(unfold(y))y/x]e : (pa.a -> t) -> t

where we recognize the term in the bottom as f. Call the above
derivation D1. We also get

D1
D1                          -------------------------- (fold)
G |- f : (pa.a -> t) -> t    G |- fold(f) : pa.a -> t
-------------------------------------------------------- (app)
G |- f(fold(f)) : t

So we see that our encoding at least has the right type.

Next we check that it has the right operational behaviour:

fix(x.e)
=== f(fold(f))
~~> [(unfold(fold(f))fold(f)/x] e
??? [f(fold(f))/x] e
=== [fix(x.e)/x] e

The question is, how do I show the step labelled '???'? To be
continued...

 Fiore, Marcelo P., "Axiomatic Domain Theory in Categories of
Partial Maps", PhD thesis, The University of Edinburgh
Department of Computer Science, October 1994, v+282 pp.

 I'm punning on the visual resemblence between 'p' and the
non-ASCII greek letter rho, which is my preferred binder for
recursive types.
```