freemonad: Update the Free monad notebook
Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
This commit is contained in:
parent
91050d615a
commit
cce60e0790
1 changed files with 201 additions and 32 deletions
233
freemonad.ipynb
233
freemonad.ipynb
|
@ -2,7 +2,7 @@
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 4,
|
"execution_count": 3,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -415,12 +415,17 @@
|
||||||
"\n",
|
"\n",
|
||||||
":t (Fix (Output 'A' (Fix Done)))\n",
|
":t (Fix (Output 'A' (Fix Done)))\n",
|
||||||
"\n",
|
"\n",
|
||||||
":t (Fix (Bell (Fix (Output 'A' (Fix Done)))))"
|
":t (Fix (Bell (Fix (Output 'A' (Fix Done)))))\n",
|
||||||
|
"\n",
|
||||||
|
"-- cosine x = x\n",
|
||||||
|
"-- x = 0.7...\n",
|
||||||
|
"\n",
|
||||||
|
"-- f x = x"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": 10,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -432,6 +437,108 @@
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "display_data"
|
"output_type": "display_data"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"120"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/html": [
|
||||||
|
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||||||
|
".hoogle-doc {\n",
|
||||||
|
"display: block;\n",
|
||||||
|
"padding-bottom: 1.3em;\n",
|
||||||
|
"padding-left: 0.4em;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-code {\n",
|
||||||
|
"display: block;\n",
|
||||||
|
"font-family: monospace;\n",
|
||||||
|
"white-space: pre;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-text {\n",
|
||||||
|
"display: block;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-name {\n",
|
||||||
|
"color: green;\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-head {\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-sub {\n",
|
||||||
|
"display: block;\n",
|
||||||
|
"margin-left: 0.4em;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-package {\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"font-style: italic;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-module {\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"}\n",
|
||||||
|
".hoogle-class {\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"}\n",
|
||||||
|
".get-type {\n",
|
||||||
|
"color: green;\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"font-family: monospace;\n",
|
||||||
|
"display: block;\n",
|
||||||
|
"white-space: pre-wrap;\n",
|
||||||
|
"}\n",
|
||||||
|
".show-type {\n",
|
||||||
|
"color: green;\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"font-family: monospace;\n",
|
||||||
|
"margin-left: 1em;\n",
|
||||||
|
"}\n",
|
||||||
|
".mono {\n",
|
||||||
|
"font-family: monospace;\n",
|
||||||
|
"display: block;\n",
|
||||||
|
"}\n",
|
||||||
|
".err-msg {\n",
|
||||||
|
"color: red;\n",
|
||||||
|
"font-style: italic;\n",
|
||||||
|
"font-family: monospace;\n",
|
||||||
|
"white-space: pre;\n",
|
||||||
|
"display: block;\n",
|
||||||
|
"}\n",
|
||||||
|
"#unshowable {\n",
|
||||||
|
"color: red;\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"}\n",
|
||||||
|
".err-msg.in.collapse {\n",
|
||||||
|
"padding-top: 0.7em;\n",
|
||||||
|
"}\n",
|
||||||
|
".highlight-code {\n",
|
||||||
|
"white-space: pre;\n",
|
||||||
|
"font-family: monospace;\n",
|
||||||
|
"}\n",
|
||||||
|
".suggestion-warning { \n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"color: rgb(200, 130, 0);\n",
|
||||||
|
"}\n",
|
||||||
|
".suggestion-error { \n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"color: red;\n",
|
||||||
|
"}\n",
|
||||||
|
".suggestion-name {\n",
|
||||||
|
"font-weight: bold;\n",
|
||||||
|
"}\n",
|
||||||
|
"</style><span class='get-type'>fact' :: forall p. (Eq p, Num p) => (p -> p) -> p -> p</span>"
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
"fact' :: forall p. (Eq p, Num p) => (p -> p) -> p -> p"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
|
@ -443,14 +550,22 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
|
"{-# LANGUAGE FlexibleContexts #-}\n",
|
||||||
|
"\n",
|
||||||
"-- https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Monad-Fix.html\n",
|
"-- https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Monad-Fix.html\n",
|
||||||
"import Control.Monad.Fix\n",
|
"import Control.Monad.Fix\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
"-- fix :: (a -> a) -> a\n",
|
||||||
|
"-- fix f = let {x = f x} in x\n",
|
||||||
|
"\n",
|
||||||
"let fac n = if n <= 1 then 1 else n * fac (n-1) in fac 5\n",
|
"let fac n = if n <= 1 then 1 else n * fac (n-1) in fac 5\n",
|
||||||
"\n",
|
"\n",
|
||||||
"fix (\\rec n -> if n <= 1 then 1 else n * rec (n-1)) 5\n",
|
"fix (\\rec n -> if n <= 1 then 1 else n * rec (n-1)) 5\n",
|
||||||
"\n",
|
"\n",
|
||||||
"-- fact' rec n = if n == 0 then 1 else n * rec (n-1)\n",
|
"-- fix fact' 5\n",
|
||||||
|
"fact' rec n = if n == 0 then 1 else n * rec (n-1)\n",
|
||||||
|
"\n",
|
||||||
|
":t fact'\n",
|
||||||
"\n",
|
"\n",
|
||||||
"-- f = fact' f\n",
|
"-- f = fact' f\n",
|
||||||
"-- = \\n -> if n == 0 then 1 else n * f (n-1)\n",
|
"-- = \\n -> if n == 0 then 1 else n * f (n-1)\n",
|
||||||
|
@ -470,12 +585,14 @@
|
||||||
" else (n-1) * (if n-2 == 0 then 1\n",
|
" else (n-1) * (if n-2 == 0 then 1\n",
|
||||||
" else (n-2) * fix fact' (n-3)))\n",
|
" else (n-2) * fix fact' (n-3)))\n",
|
||||||
"= ...\n",
|
"= ...\n",
|
||||||
"-}"
|
"-}\n",
|
||||||
|
"\n",
|
||||||
|
"fix fact' 5"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 15,
|
"execution_count": 5,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -579,6 +696,8 @@
|
||||||
"source": [
|
"source": [
|
||||||
"data FixE f e = Fix (f (FixE f e)) | Throw e\n",
|
"data FixE f e = Fix (f (FixE f e)) | Throw e\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
"-- data Free f r = Free (f (Free f r)) | Pure r\n",
|
||||||
|
"\n",
|
||||||
"catch :: (Functor f) => FixE f e1 -> (e1 -> FixE f e2) -> FixE f e2\n",
|
"catch :: (Functor f) => FixE f e1 -> (e1 -> FixE f e2) -> FixE f e2\n",
|
||||||
"catch (Fix x) f = Fix (fmap (flip catch f) x)\n",
|
"catch (Fix x) f = Fix (fmap (flip catch f) x)\n",
|
||||||
"catch (Throw e) f = f e\n",
|
"catch (Throw e) f = f e\n",
|
||||||
|
@ -592,6 +711,7 @@
|
||||||
"\n",
|
"\n",
|
||||||
"-- output 'A'\n",
|
"-- output 'A'\n",
|
||||||
"-- throw IncompleteException\n",
|
"-- throw IncompleteException\n",
|
||||||
|
"-- output 'B'\n",
|
||||||
"subroutine = Fix (Output 'A' (Throw IncompleteException)) :: FixE (Toy Char) IncompleteException\n",
|
"subroutine = Fix (Output 'A' (Throw IncompleteException)) :: FixE (Toy Char) IncompleteException\n",
|
||||||
"\n",
|
"\n",
|
||||||
"-- try {subroutine}\n",
|
"-- try {subroutine}\n",
|
||||||
|
@ -604,7 +724,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 23,
|
"execution_count": 6,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -691,10 +811,10 @@
|
||||||
".suggestion-name {\n",
|
".suggestion-name {\n",
|
||||||
"font-weight: bold;\n",
|
"font-weight: bold;\n",
|
||||||
"}\n",
|
"}\n",
|
||||||
"</style><span class='get-type'>output :: forall b. b -> Free (Toy b) ()</span>"
|
"</style><span class='get-type'>output :: forall b (m :: * -> *). MonadFree (Toy b) m => b -> m ()</span>"
|
||||||
],
|
],
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"output :: forall b. b -> Free (Toy b) ()"
|
"output :: forall b (m :: * -> *). MonadFree (Toy b) m => b -> m ()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
|
@ -784,10 +904,10 @@
|
||||||
".suggestion-name {\n",
|
".suggestion-name {\n",
|
||||||
"font-weight: bold;\n",
|
"font-weight: bold;\n",
|
||||||
"}\n",
|
"}\n",
|
||||||
"</style><span class='get-type'>bell :: forall b. Free (Toy b) ()</span>"
|
"</style><span class='get-type'>bell :: forall b (m :: * -> *). MonadFree (Toy b) m => m ()</span>"
|
||||||
],
|
],
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"bell :: forall b. Free (Toy b) ()"
|
"bell :: forall b (m :: * -> *). MonadFree (Toy b) m => m ()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
|
@ -877,10 +997,10 @@
|
||||||
".suggestion-name {\n",
|
".suggestion-name {\n",
|
||||||
"font-weight: bold;\n",
|
"font-weight: bold;\n",
|
||||||
"}\n",
|
"}\n",
|
||||||
"</style><span class='get-type'>done :: forall b r. Free (Toy b) r</span>"
|
"</style><span class='get-type'>done :: forall b (m :: * -> *) a. MonadFree (Toy b) m => m a</span>"
|
||||||
],
|
],
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"done :: forall b r. Free (Toy b) r"
|
"done :: forall b (m :: * -> *) a. MonadFree (Toy b) m => m a"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
|
@ -900,6 +1020,18 @@
|
||||||
"-}\n",
|
"-}\n",
|
||||||
"\n",
|
"\n",
|
||||||
"{-|\n",
|
"{-|\n",
|
||||||
|
"(>>=) :: forall a b. m a -> (a -> m b) -> m b\n",
|
||||||
|
"catch :: (Functor f) => FixE f e1 -> (e1 -> FixE f e2) -> FixE f e2\n",
|
||||||
|
"\n",
|
||||||
|
"FixE f --- m\n",
|
||||||
|
"e1 --- a\n",
|
||||||
|
"e2 --- b\n",
|
||||||
|
"\n",
|
||||||
|
"catch -- >>=\n",
|
||||||
|
"Throw -- Pure\n",
|
||||||
|
"-}\n",
|
||||||
|
"\n",
|
||||||
|
"{-|\n",
|
||||||
"output :: a -> Free (Toy a) ()\n",
|
"output :: a -> Free (Toy a) ()\n",
|
||||||
"output x = Free (Output x (Pure ()))\n",
|
"output x = Free (Output x (Pure ()))\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
@ -913,6 +1045,10 @@
|
||||||
"liftF command = Free (fmap Pure command)\n",
|
"liftF command = Free (fmap Pure command)\n",
|
||||||
"-}\n",
|
"-}\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
"-- There is some Functor f => Free f is a monad\n",
|
||||||
|
"\n",
|
||||||
|
"-- Toy b is a Functor, Free (Toy b) is a monad\n",
|
||||||
|
"\n",
|
||||||
"output x = liftF (Output x ())\n",
|
"output x = liftF (Output x ())\n",
|
||||||
"bell = liftF (Bell ())\n",
|
"bell = liftF (Bell ())\n",
|
||||||
"done = liftF Done\n",
|
"done = liftF Done\n",
|
||||||
|
@ -926,6 +1062,7 @@
|
||||||
"\n",
|
"\n",
|
||||||
"program :: Free (Toy Char) r\n",
|
"program :: Free (Toy Char) r\n",
|
||||||
"program = do\n",
|
"program = do\n",
|
||||||
|
" bell\n",
|
||||||
" subroutine\n",
|
" subroutine\n",
|
||||||
" bell\n",
|
" bell\n",
|
||||||
" done"
|
" done"
|
||||||
|
@ -933,12 +1070,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 24,
|
"execution_count": 7,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
|
"bell\n",
|
||||||
"output 'A'\n",
|
"output 'A'\n",
|
||||||
"bell\n",
|
"bell\n",
|
||||||
"done"
|
"done"
|
||||||
|
@ -1134,24 +1272,6 @@
|
||||||
"pretty (output 'A' >> (done >> output 'C'))"
|
"pretty (output 'A' >> (done >> output 'C'))"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 27,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"import Control.Exception\n",
|
|
||||||
"\n",
|
|
||||||
"ringBell :: IO ()\n",
|
|
||||||
"ringBell = undefined\n",
|
|
||||||
"\n",
|
|
||||||
"interpret :: (Show b) => Free (Toy b) r -> IO ()\n",
|
|
||||||
"interpret (Free (Output b x)) = print b >> interpret x\n",
|
|
||||||
"interpret (Free (Bell x)) = ringBell >> interpret x\n",
|
|
||||||
"interpret (Free Done ) = return ()\n",
|
|
||||||
"interpret (Pure r) = throwIO (userError \"Improper termination\")"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 43,
|
"execution_count": 43,
|
||||||
|
@ -1172,6 +1292,55 @@
|
||||||
"-}"
|
"-}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 9,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"{-|\n",
|
||||||
|
"\n",
|
||||||
|
"data Request =\n",
|
||||||
|
" Look Direction\n",
|
||||||
|
" | ReadLine\n",
|
||||||
|
" | Fire Direction\n",
|
||||||
|
" | WriteLine String\n",
|
||||||
|
" \n",
|
||||||
|
"data Response =\n",
|
||||||
|
" Image Picture -- Response for Look\n",
|
||||||
|
" | ChatLine String -- Response for Read\n",
|
||||||
|
" | Succeeded Bool -- Response for Write\n",
|
||||||
|
" \n",
|
||||||
|
"data Interaction next =\n",
|
||||||
|
" Look Direction (Image -> next)\n",
|
||||||
|
" | Fire Direction next\n",
|
||||||
|
" | ReadLine (String -> next)\n",
|
||||||
|
" | WriteLine String (Bool -> next)\n",
|
||||||
|
" \n",
|
||||||
|
"instance Functor Interaction where\n",
|
||||||
|
" fmap f (Look dir g) = Look dir (f . g)\n",
|
||||||
|
" fmap f (Fire dir x) = Fire dir (f x)\n",
|
||||||
|
" fmap f (ReadLine g) = ReadLine (f . g)\n",
|
||||||
|
" fmap f (WriteLine s g) = WriteLine s (f . g)\n",
|
||||||
|
" \n",
|
||||||
|
"interpret :: Program r -> Game r\n",
|
||||||
|
"interpret prog = case prog of\n",
|
||||||
|
" Free (Look dir g) -> do\n",
|
||||||
|
" img <- collectImage dir\n",
|
||||||
|
" interpret (g img)\n",
|
||||||
|
" Free (Fire dir next) -> do\n",
|
||||||
|
" sendBullet dir\n",
|
||||||
|
" interpret next\n",
|
||||||
|
" Free (ReadLine g) -> do\n",
|
||||||
|
" str <- getChatLine\n",
|
||||||
|
" interpret (g str)\n",
|
||||||
|
" Free (WriteLine s g) ->\n",
|
||||||
|
" putChatLine s\n",
|
||||||
|
" interpret (g True)\n",
|
||||||
|
" Pure r -> return r\n",
|
||||||
|
"-}"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 45,
|
"execution_count": 45,
|
||||||
|
|
Loading…
Reference in a new issue