Rebuild docs

This commit is contained in:
Simon Forman
2020-05-17 16:40:58 -07:00
parent ef6411205d
commit 56da4690d0
84 changed files with 7456 additions and 7972 deletions
+109 -109
View File
@@ -1,8 +1,8 @@
Treating Trees II: ``treestep``
===============================
Let's consider a tree structure, similar to one described `"Why
functional programming matters" by John
Lets consider a tree structure, similar to one described `Why
functional programming matters by John
Hughes <https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf>`__,
that consists of a node value followed by zero or more child trees. (The
asterisk is meant to indicate the `Kleene
@@ -10,7 +10,7 @@ star <https://en.wikipedia.org/wiki/Kleene_star>`__.)
::
tree = [] | [node tree*]
tree = [] | [node tree*]
In the spirit of ``step`` we are going to define a combinator
``treestep`` which expects a tree and three additional items: a
@@ -18,15 +18,15 @@ base-case function ``[B]``, and two quoted programs ``[N]`` and ``[C]``.
::
tree [B] [N] [C] treestep
tree [B] [N] [C] treestep
If the current tree node is empty then just execute ``B``:
::
[] [B] [N] [C] treestep
---------------------------
[] B
[] [B] [N] [C] treestep
---------------------------
[] B
Otherwise, evaluate ``N`` on the node value, ``map`` the whole function
(abbreviated here as ``K``) over the child trees recursively, and then
@@ -34,11 +34,11 @@ combine the result with ``C``.
::
[node tree*] [B] [N] [C] treestep
--------------------------------------- w/ K == [B] [N] [C] treestep
node N [tree*] [K] map C
[node tree*] [B] [N] [C] treestep
--------------------------------------- w/ K == [B] [N] [C] treestep
node N [tree*] [K] map C
(Later on we'll experiment with making ``map`` part of ``C`` so you can
(Later on well experiment with making ``map`` part of ``C`` so you can
use other combinators.)
Derive the recursive function.
@@ -49,59 +49,59 @@ will produce.
::
K == [not] [B] [R0] [R1] genrec
== [not] [B] [R0 [K] R1] ifte
K == [not] [B] [R0] [R1] genrec
== [not] [B] [R0 [K] R1] ifte
So we just have to derive ``J``:
::
J == R0 [K] R1
J == R0 [K] R1
The behavior of ``J`` is to accept a (non-empty) tree node and arrive at
the desired outcome.
::
[node tree*] J
------------------------------
node N [tree*] [K] map C
[node tree*] J
------------------------------
node N [tree*] [K] map C
So ``J`` will have some form like:
::
J == ... [N] ... [K] ... [C] ...
J == ... [N] ... [K] ... [C] ...
Let's dive in. First, unquote the node and ``dip`` ``N``.
Lets dive in. First, unquote the node and ``dip`` ``N``.
::
[node tree*] uncons [N] dip
node [tree*] [N] dip
node N [tree*]
[node tree*] uncons [N] dip
node [tree*] [N] dip
node N [tree*]
Next, ``map`` ``K`` over the child trees and combine with ``C``.
::
node N [tree*] [K] map C
node N [tree*] [K] map C
node N [K.tree*] C
node N [tree*] [K] map C
node N [tree*] [K] map C
node N [K.tree*] C
So:
::
J == uncons [N] dip [K] map C
J == uncons [N] dip [K] map C
Plug it in and convert to ``genrec``:
::
K == [not] [B] [J ] ifte
== [not] [B] [uncons [N] dip [K] map C] ifte
== [not] [B] [uncons [N] dip] [map C] genrec
K == [not] [B] [J ] ifte
== [not] [B] [uncons [N] dip [K] map C] ifte
== [not] [B] [uncons [N] dip] [map C] genrec
Extract the givens to parameterize the program.
-----------------------------------------------
@@ -110,26 +110,26 @@ Working backwards:
::
[not] [B] [uncons [N] dip] [map C] genrec
[B] [not] swap [uncons [N] dip] [map C] genrec
[B] [uncons [N] dip] [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^
[B] [[N] dip] [uncons] swoncat [[not] swap] dip [map C] genrec
[B] [N] [dip] cons [uncons] swoncat [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^
[not] [B] [uncons [N] dip] [map C] genrec
[B] [not] swap [uncons [N] dip] [map C] genrec
[B] [uncons [N] dip] [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^
[B] [[N] dip] [uncons] swoncat [[not] swap] dip [map C] genrec
[B] [N] [dip] cons [uncons] swoncat [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Extract a couple of auxiliary definitions:
::
TS.0 == [[not] swap] dip
TS.1 == [dip] cons [uncons] swoncat
TS.0 == [[not] swap] dip
TS.1 == [dip] cons [uncons] swoncat
::
[B] [N] TS.1 TS.0 [map C] genrec
[B] [N] [map C] [TS.1 TS.0] dip genrec
[B] [N] [C] [map] swoncat [TS.1 TS.0] dip genrec
[B] [N] TS.1 TS.0 [map C] genrec
[B] [N] [map C] [TS.1 TS.0] dip genrec
[B] [N] [C] [map] swoncat [TS.1 TS.0] dip genrec
The givens are all to the left so we have our definition.
@@ -140,10 +140,10 @@ Working backwards:
::
[not] [B] [uncons [N] dip] [map C] genrec
[not] [B] [N] [dip] cons [uncons] swoncat [map C] genrec
[B] [N] [not] roll> [dip] cons [uncons] swoncat [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[not] [B] [uncons [N] dip] [map C] genrec
[not] [B] [N] [dip] cons [uncons] swoncat [map C] genrec
[B] [N] [not] roll> [dip] cons [uncons] swoncat [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Define ``treestep``
-------------------
@@ -171,7 +171,7 @@ all nodes in a tree with this function:
::
sumtree == [pop 0] [] [sum +] treestep
sumtree == [pop 0] [] [sum +] treestep
.. code:: ipython2
@@ -181,9 +181,9 @@ Running this function on an empty tree value gives zero:
::
[] [pop 0] [] [sum +] treestep
------------------------------------
0
[] [pop 0] [] [sum +] treestep
------------------------------------
0
.. code:: ipython2
@@ -199,11 +199,11 @@ Running it on a non-empty node:
::
[n tree*] [pop 0] [] [sum +] treestep
n [tree*] [[pop 0] [] [sum +] treestep] map sum +
n [ ... ] sum +
n m +
n+m
[n tree*] [pop 0] [] [sum +] treestep
n [tree*] [[pop 0] [] [sum +] treestep] map sum +
n [ ... ] sum +
n m +
n+m
.. code:: ipython2
@@ -310,7 +310,7 @@ Redefining the Ordered Binary Tree in terms of ``treestep``.
::
Tree = [] | [[key value] left right]
Tree = [] | [[key value] left right]
What kind of functions can we write for this with our ``treestep``?
@@ -318,26 +318,26 @@ The pattern for processing a non-empty node is:
::
node N [tree*] [K] map C
node N [tree*] [K] map C
Plugging in our BTree structure:
::
[key value] N [left right] [K] map C
[key value] N [left right] [K] map C
Traversal
~~~~~~~~~
::
[key value] first [left right] [K] map i
key [value] [left right] [K] map i
key [left right] [K] map i
key [lkey rkey ] i
key lkey rkey
[key value] first [left right] [K] map i
key [value] [left right] [K] map i
key [left right] [K] map i
key [lkey rkey ] i
key lkey rkey
This doesn't quite work:
This doesnt quite work:
.. code:: ipython2
@@ -349,25 +349,25 @@ This doesn't quite work:
3 'B' 'B'
Doesn't work because ``map`` extracts the ``first`` item of whatever its
Doesnt work because ``map`` extracts the ``first`` item of whatever its
mapped function produces. We have to return a list, rather than
depositing our results directly on the stack.
::
[key value] N [left right] [K] map C
[key value] N [left right] [K] map C
[key value] first [left right] [K] map flatten cons
key [left right] [K] map flatten cons
key [[lk] [rk] ] flatten cons
key [ lk rk ] cons
[key lk rk ]
[key value] first [left right] [K] map flatten cons
key [left right] [K] map flatten cons
key [[lk] [rk] ] flatten cons
key [ lk rk ] cons
[key lk rk ]
So:
::
[] [first] [flatten cons] treestep
[] [first] [flatten cons] treestep
.. code:: ipython2
@@ -388,18 +388,18 @@ From here:
::
key [[lk] [rk]] C
key [[lk] [rk]] i
key [lk] [rk] roll<
[lk] [rk] key swons concat
[lk] [key rk] concat
[lk key rk]
key [[lk] [rk]] C
key [[lk] [rk]] i
key [lk] [rk] roll<
[lk] [rk] key swons concat
[lk] [key rk] concat
[lk key rk]
So:
::
[] [i roll< swons concat] [first] treestep
[] [i roll< swons concat] [first] treestep
.. code:: ipython2
@@ -414,20 +414,20 @@ So:
With ``treegrind``?
-------------------
The ``treegrind`` function doesn't include the ``map`` combinator, so
The ``treegrind`` function doesnt include the ``map`` combinator, so
the ``[C]`` function must arrange to use some combinator on the quoted
recursive copy ``[K]``. With this function, the pattern for processing a
non-empty node is:
::
node N [tree*] [K] C
node N [tree*] [K] C
Plugging in our BTree structure:
::
[key value] N [left right] [K] C
[key value] N [left right] [K] C
.. code:: ipython2
@@ -454,7 +454,7 @@ Iteration through the nodes
[3 0] 'N' [2 0] 'N' [9 0] 'N' [5 0] 'N' [4 0] 'N' [8 0] 'N' [6 0] 'N' [7 0] 'N'
Sum the nodes' keys.
Sum the nodes keys.
.. code:: ipython2
@@ -485,28 +485,28 @@ I think we do:
::
[B] [N] [C] treegrind
[B] [N] [C] treegrind
We'll start by saying that the base-case (the key is not in the tree) is
Well start by saying that the base-case (the key is not in the tree) is
user defined, and the per-node function is just the query key literal:
::
[B] [query_key] [C] treegrind
[B] [query_key] [C] treegrind
This means we just have to define ``C`` from:
::
[key value] query_key [left right] [K] C
[key value] query_key [left right] [K] C
Let's try ``cmp``:
Lets try ``cmp``:
::
C == P [T>] [E] [T<] cmp
C == P [T>] [E] [T<] cmp
[key value] query_key [left right] [K] P [T>] [E] [T<] cmp
[key value] query_key [left right] [K] P [T>] [E] [T<] cmp
The predicate ``P``
~~~~~~~~~~~~~~~~~~~
@@ -516,16 +516,16 @@ equal):
::
[key value] query_key [left right] [K] P
[key value] query_key [left right] [K] roll<
[key value] [left right] [K] query_key [roll< uncons swap] dip
[key value] query_key [left right] [K] P
[key value] query_key [left right] [K] roll<
[key value] [left right] [K] query_key [roll< uncons swap] dip
[key value] [left right] [K] roll< uncons swap query_key
[left right] [K] [key value] uncons swap query_key
[left right] [K] key [value] swap query_key
[left right] [K] [value] key query_key
[key value] [left right] [K] roll< uncons swap query_key
[left right] [K] [key value] uncons swap query_key
[left right] [K] key [value] swap query_key
[left right] [K] [value] key query_key
P == roll< [roll< uncons swap] dip
P == roll< [roll< uncons swap] dip
(Possibly with a swap at the end? Or just swap ``T<`` and ``T>``.)
@@ -533,15 +533,15 @@ So now:
::
[left right] [K] [value] key query_key [T>] [E] [T<] cmp
[left right] [K] [value] key query_key [T>] [E] [T<] cmp
Becomes one of these three:
::
[left right] [K] [value] T>
[left right] [K] [value] E
[left right] [K] [value] T<
[left right] [K] [value] T>
[left right] [K] [value] E
[left right] [K] [value] T<
``E``
~~~~~
@@ -550,27 +550,27 @@ Easy.
::
E == roll> popop first
E == roll> popop first
``T<`` and ``T>``
~~~~~~~~~~~~~~~~~
::
T< == pop [first] dip i
T> == pop [second] dip i
T< == pop [first] dip i
T> == pop [second] dip i
Putting it together
-------------------
::
T> == pop [first] dip i
T< == pop [second] dip i
E == roll> popop first
P == roll< [roll< uncons swap] dip
T> == pop [first] dip i
T< == pop [second] dip i
E == roll> popop first
P == roll< [roll< uncons swap] dip
Tree-get == [P [T>] [E] [T<] cmp] treegrind
Tree-get == [P [T>] [E] [T<] cmp] treegrind
To me, that seems simpler than the ``genrec`` version.