Bunches of new docs.

Type inference!

A new treatment of recursion combinator patterns.
This commit is contained in:
Simon Forman
2018-06-21 21:13:50 -07:00
parent 049cfd22b7
commit ca05ea404a
32 changed files with 42303 additions and 1064 deletions
+109 -150
View File
@@ -1,12 +1,5 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)"
]
},
{
"cell_type": "code",
"execution_count": 1,
@@ -16,6 +9,13 @@
"from notebook_preamble import J, V, define"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -27,9 +27,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
" -b +/- sqrt(b^2 - 4 * a * c)\n",
" -----------------------------\n",
" 2 * a"
" -b ± sqrt(b^2 - 4 * a * c)\n",
" --------------------------------\n",
" 2 * a"
]
},
{
@@ -44,42 +44,52 @@
"metadata": {},
"source": [
"## Write a straightforward program with variable names.\n",
"\n",
" b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
"\n",
"We use `cleave` to compute the sum and difference and then `app2` to finish computing both roots using a quoted program `[2a truediv]` built with `cons`."
"This math translates to Joy code in a straightforward manner. We are going to use named variables to keep track of the arguments, then write a definition without them."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Check it.\n",
"Evaluating by hand:\n",
"\n",
" b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
" -b b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
" -b b^2 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
" -b b^2 4ac - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
" -b b^2-4ac sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
" -b sqrt(b^2-4ac) [+] [-] cleave a 2 * [truediv] cons app2\n",
"\n",
" -b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) a 2 * [truediv] cons app2\n",
" -b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) 2a [truediv] cons app2\n",
" -b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) [2a truediv] app2\n",
" -b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a\n",
"\n",
"(Eventually well be able to use e.g. Sympy versions of the Joy commands to do this sort of thing symbolically. This is part of what is meant by a “categorical” language.)"
"### `-b`\n",
" b neg"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Cleanup\n",
" -b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a roll< pop\n",
" -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a -b pop\n",
" -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a"
"### `sqrt(b^2 - 4 * a * c)`\n",
" b sqr 4 a c * * - sqrt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `/2a`\n",
" a 2 * /"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `±`\n",
"There is a function `pm` that accepts two values on the stack and replaces them with their sum and difference.\n",
"\n",
" pm == [+] [-] cleave popdd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Putting Them Together\n",
"\n",
" b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
"\n",
"We use `app2` to compute both roots by using a quoted program `[2a /]` built with `cons`."
]
},
{
@@ -87,12 +97,15 @@
"metadata": {},
"source": [
"## Derive a definition.\n",
"Working backwards we use `dip` and `dipd` to extract the code from the variables:\n",
"\n",
" b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop\n",
" b [neg] dupdip sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop\n",
" b a c [[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop\n",
" b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop\n",
" b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop"
" b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2\n",
" b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
" b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
"\n",
"The three arguments are to the left, so we can \"chop off\" everything to the right and say it's the definition of the `quadratic` function:"
]
},
{
@@ -101,7 +114,14 @@
"metadata": {},
"outputs": [],
"source": [
"define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop')"
"define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's try it out:"
]
},
{
@@ -125,137 +145,76 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simplify\n",
"We can define a `pm` plus-or-minus function:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" pm == [+] [-] cleave popdd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then `quadratic` becomes:"
"If you look at the Joy evaluation trace you can see that the first few lines are the `dip` and `dipd` combinators building the main program by incorporating the values on the stack. Then that program runs and you get the results. This is pretty typical of Joy code."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2')"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-0.3819660112501051 -2.618033988749895\n"
" . -5 1 4 quadratic\n",
" -5 . 1 4 quadratic\n",
" -5 1 . 4 quadratic\n",
" -5 1 4 . quadratic\n",
" -5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
" -5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
"-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2\n",
" -5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2\n",
" -5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2\n",
" -5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" -5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" -5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2\n",
" 5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2\n",
" 5 25 16 . - sqrt pm 1 2 * [/] cons app2\n",
" 5 9 . sqrt pm 1 2 * [/] cons app2\n",
" 5 3.0 . pm 1 2 * [/] cons app2\n",
" 8.0 2.0 . 1 2 * [/] cons app2\n",
" 8.0 2.0 1 . 2 * [/] cons app2\n",
" 8.0 2.0 1 2 . * [/] cons app2\n",
" 8.0 2.0 2 . [/] cons app2\n",
" 8.0 2.0 2 [/] . cons app2\n",
" 8.0 2.0 [2 /] . app2\n",
" [8.0] [2 /] . infra first [2.0] [2 /] infra first\n",
" 8.0 . 2 / [] swaack first [2.0] [2 /] infra first\n",
" 8.0 2 . / [] swaack first [2.0] [2 /] infra first\n",
" 4.0 . [] swaack first [2.0] [2 /] infra first\n",
" 4.0 [] . swaack first [2.0] [2 /] infra first\n",
" [4.0] . first [2.0] [2 /] infra first\n",
" 4.0 . [2.0] [2 /] infra first\n",
" 4.0 [2.0] . [2 /] infra first\n",
" 4.0 [2.0] [2 /] . infra first\n",
" 2.0 . 2 / [4.0] swaack first\n",
" 2.0 2 . / [4.0] swaack first\n",
" 1.0 . [4.0] swaack first\n",
" 1.0 [4.0] . swaack first\n",
" 4.0 [1.0] . first\n",
" 4.0 1.0 . \n"
]
}
],
"source": [
"J('3 1 1 quadratic')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Define a \"native\" `pm` function.\n",
"The definition of `pm` above is pretty elegant, but the implementation takes a lot of steps relative to what it's accomplishing. Since we are likely to use `pm` more than once in the future, let's write a primitive in Python and add it to the dictionary. (This has been done already.)"
"V('-5 1 4 quadratic')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def pm(stack):\n",
" a, (b, stack) = stack\n",
" p, m, = b + a, b - a\n",
" return m, (p, stack)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The resulting trace is short enough to fit on a page."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" . 3 1 1 quadratic\n",
" 3 . 1 1 quadratic\n",
" 3 1 . 1 quadratic\n",
" 3 1 1 . quadratic\n",
" 3 1 1 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2\n",
" 3 1 1 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2\n",
" 3 1 1 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [truediv] cons app2\n",
" 3 1 1 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [truediv] cons app2\n",
" 3 1 1 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [truediv] cons app2\n",
" 3 . [neg] dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" 3 [neg] . dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" 3 . neg 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 . 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 3 . sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 3 . dup mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 3 3 . mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 9 . 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 9 4 . 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 9 4 1 . 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 9 4 1 1 . * * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 9 4 1 . * - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 9 4 . - sqrt pm 1 2 * [truediv] cons app2\n",
" -3 5 . sqrt pm 1 2 * [truediv] cons app2\n",
" -3 2.23606797749979 . pm 1 2 * [truediv] cons app2\n",
" -0.7639320225002102 -5.23606797749979 . 1 2 * [truediv] cons app2\n",
" -0.7639320225002102 -5.23606797749979 1 . 2 * [truediv] cons app2\n",
" -0.7639320225002102 -5.23606797749979 1 2 . * [truediv] cons app2\n",
" -0.7639320225002102 -5.23606797749979 2 . [truediv] cons app2\n",
" -0.7639320225002102 -5.23606797749979 2 [truediv] . cons app2\n",
" -0.7639320225002102 -5.23606797749979 [2 truediv] . app2\n",
" [-0.7639320225002102] [2 truediv] . infra first [-5.23606797749979] [2 truediv] infra first\n",
" -0.7639320225002102 . 2 truediv [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
" -0.7639320225002102 2 . truediv [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
" -0.3819660112501051 . [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
" -0.3819660112501051 [] . swaack first [-5.23606797749979] [2 truediv] infra first\n",
" [-0.3819660112501051] . first [-5.23606797749979] [2 truediv] infra first\n",
" -0.3819660112501051 . [-5.23606797749979] [2 truediv] infra first\n",
" -0.3819660112501051 [-5.23606797749979] . [2 truediv] infra first\n",
"-0.3819660112501051 [-5.23606797749979] [2 truediv] . infra first\n",
" -5.23606797749979 . 2 truediv [-0.3819660112501051] swaack first\n",
" -5.23606797749979 2 . truediv [-0.3819660112501051] swaack first\n",
" -2.618033988749895 . [-0.3819660112501051] swaack first\n",
" -2.618033988749895 [-0.3819660112501051] . swaack first\n",
" -0.3819660112501051 [-2.618033988749895] . first\n",
" -0.3819660112501051 -2.618033988749895 . \n"
]
}
],
"source": [
"V('3 1 1 quadratic')"
]
"source": []
}
],
"metadata": {