We'll need a number of classes of functions to help us maneuver in the
presence of box types. We will want to define a different instance of
We'll need a number of classes of functions to help us maneuver in the
presence of box types. We will want to define a different instance of
<code>mid (/εmaidεnt@tI/ aka unit, return, pure): P -> <u>P</u></code>
<code>map (/maep/): (P -> Q) -> <u>P</u> -> <u>Q</u></code>
<code>mid (/εmaidεnt@tI/ aka unit, return, pure): P -> <u>P</u></code>
<code>map (/maep/): (P -> Q) -> <u>P</u> -> <u>Q</u></code>
if there are in addition `map2`, `mid`, and `mapply`. (With
`map2` in hand, `map3`, `map4`, ... `mapN` are easily definable.)
if there are in addition `map2`, `mid`, and `mapply`. (With
`map2` in hand, `map3`, `map4`, ... `mapN` are easily definable.)
-* ***Monad*** ("composable") A MapNable box type is a *Monad* if there
- is in addition an `mcompose` and a `join` such that `mid` is be
+* ***Monad*** ("composables") A MapNable box type is a *Monad* if there
+ is in addition an `mcompose` and a `join` such that `mid` is
a left and right identity for `mcompose`, and `mcompose` is
associative. That is, the following "laws" must hold:
a left and right identity for `mcompose`, and `mcompose` is
associative. That is, the following "laws" must hold:
mcompose-crossy: (β -> [γ]) -> (α -> [β]) -> (α -> [γ])
mcompose-crossy f g a = [c | b <- g a, c <- f b]
mcompose-crossy: (β -> [γ]) -> (α -> [β]) -> (α -> [γ])
mcompose-crossy f g a = [c | b <- g a, c <- f b]
In words, `mcompose f g a` feeds the a (which has type α) to g, which
returns a list of βs; each β in that list is fed to f, which returns a
In words, `mcompose f g a` feeds the a (which has type α) to g, which
returns a list of βs; each β in that list is fed to f, which returns a