styling and a draft

This commit is contained in:
Alexander 2025-06-10 23:21:42 -04:00
parent c33fdf4cbb
commit 02c80ce9dd
17 changed files with 63 additions and 13 deletions

View file

@ -1,3 +1,43 @@
# Living Free with Monads # Living Free with Monads
Explicit record passing makes OCaml feel _good_. It's an old tradition that any programmer who thinks they know something useful about monads eventually goes off and writes a blog post about it.
_Anyway_ ...
Lets take a look at a `Monad` definition (yeah, I know) in OCaml and walk through the clues that suggest a monad's implementation. Modular explicits make OCaml feel _good_.
An OCaml module can be thought of as a record containing types and terms that constitutes an abstraction boundary via information hiding. OCaml's type/module system allows a programmer to selectively expose information about a module to the outside world and, dually, to selectively depend on particular module structure. Modules are the primary mechanism by which OCaml code is structured and provide programmers the machinery of composition and code reuse.
```ocaml
module type Monad = sig
type 'a t
val return : 'a -> 'a t
val bind : ('a -> 'b t) -> 'a t -> 'b t
end
```
Above is a module _signature_, which can be thought of as the analogue in module-space to a type in value-space (hence `module type` in the syntax). A module signature defines the set of all possible modules that comply with the structure it describes. In this case, we give a name to the set of modules containing _at least_ a type constructor `'a t`, a function `return : 'a -> 'a t`, and a function `bind : ('a -> 'b t) -> 'a t -> 'b t`. Abstractly, these are what constitute a monad.
It's helpful to think about what each of these items means in general before examining them in more concrete terms. `t` is a function from types to types, also known as a type constructor. `list` and `option` are such type constructors. The presence of `t` in our `Monad` signature--- specifically the fact that it's parametric--- represents the idea that a monad is essentially a _context_ around underlying computations of an abstract type. For some particular `'a` and some particular module that fits the `Monad` signature, `'a` is the type of the essential computation; that is, `t` is the generic context itself, and `'a t` is an instance of that generic context which is specific to the inner type `'a`; `'a t` is the type of alphas in the `t` sort of context. What exactly is meant by "context" here is the key to this whole endeavor, but I'll avoid addressing it directly until we're a little further along.
```ocaml
module ListMonad = struct
type 'a t = 'a list
val return : 'a -> 'a t
. . .
end
```
`list` forms a monad when equipped with suitable definitions of `return` and `bind`, though I've omitted those definitions for now to focus on the first item. The meaning of `list` as a monad--- that is, the context that `list` and its natural accompanying definitions of `bind` and `return` represent--- is interesting, broadly useful, and sufficiently non-obvious as to demand some intuition. I'll use it as a running example.
Examine the
***
// return will have embedded in it some notion of the empty or default context for a value : `'a`
A context should be thought of as some additional or different computation that is driven by the underlying computation in `'a`. In other words, ever time you work with an `'a t`, some implicit action is carried out in addition to whatever direct manipulations of the context or underlying value you perform. This implicit action is embedded in the definition of `bind`, and thus it is the definition of a `bind` function for a type constructor that fundamentally determines what the context is or means and how it behaves.
A "functor" in OCaml parlance is distinct from anything called a "functor" anywhere else, being essentially a function from modules to modules. For practical reasons, modules and value-level programs are stratified from one another in OCaml, so a functor does not literally have a function type, but the mental model is useful all the same. We will encounter some functors of both sorts later on.
(aside: this stratification is not theoretically needed, re 1ml)

View file

@ -112,28 +112,28 @@
@font-face { @font-face {
font-family: 'Mono'; font-family: 'Mono';
src: url('../assets/fonts/CommitMonoUnfancyDevNV143/CommitMonoUnfancyDevN-350-Regular.otf') format('opentype'); src: url('../assets/fonts/JuliaMono/JuliaMono_Regular.ttf') format('truetype');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Mono'; font-family: 'Mono';
src: url('../assets/fonts/CommitMonoUnfancyDevNV143/CommitMonoUnfancyDevN-350-Italic.otf') format('opentype'); src: url('../assets/fonts/JuliaMono/JuliaMono_RegularItalic.ttf') format('truetype');
font-weight: normal; font-weight: normal;
font-style: italic; font-style: italic;
} }
@font-face { @font-face {
font-family: 'Mono'; font-family: 'Mono';
src: url('../assets/fonts/CommitMonoUnfancyDevNV143/CommitMonoUnfancyDevN-700-Regular.otf') format('opentype'); src: url('../assets/fonts/JuliaMono/JuliaMono_SemiBold.ttf') format('truetype');
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Mono'; font-family: 'Mono';
src: url('../assets/fonts/CommitMonoUnfancyDevNV143/CommitMonoUnfancyDevN-700-Italic.otf') format('opentype'); src: url('../assets/fonts/JuliaMono/JuliaMono_SemiBoldItalic.ttf') format('truetype');
font-weight: bold; font-weight: bold;
font-style: italic; font-style: italic;
} }
@ -209,7 +209,8 @@ h6 {
font-size: calc(1.0 * var(--base-font-size)) font-size: calc(1.0 * var(--base-font-size))
} }
code { code, pre code {
font-family: "Mono"; font-family: "Mono";
font-size: calc(0.845 * var(--base-font-size)); font-size: calc(0.84 * var(--base-font-size));
/* font-weight: bold; */
} }

View file

@ -1,13 +1,21 @@
code:not(pre code) {
font-weight: bold;
}
:root { :root {
--darkest-color: rgb(10, 5, 0); --darkest-color: rgb(10, 5, 0);
--middle-color: rgb(60, 55, 50); --middle-color: rgb(60, 55, 50);
--lighter-color: rgb(95, 85, 80); --lighter-color: rgb(95, 85, 80);
--ui-spacing: 1.25; --ui-spacing: 1.25;
--read-spacing: 1.5; --read-spacing: 1.5;
--wide-gray: rgb(245, 240, 240);
--narrow-gray: rgb(225, 220, 220);
}
code:not(pre code) {
background-color: var(--wide-gray);
padding-left: 3px;
padding-right: 3px;
padding-top: 1px;
padding-bottom: 1px;
color: black;
border-radius: 5px;
} }
pre { pre {
@ -16,10 +24,11 @@ pre {
border-style: solid; border-style: solid;
border-radius: 3px; border-radius: 3px;
border-width: 2px; border-width: 2px;
border-color: gainsboro; border-color: var(--narrow-gray);
padding-left: 0.35em; padding-left: 0.35em;
padding-top: 0.1em; padding-top: 0.1em;
padding-bottom: 0.2em; padding-bottom: 0.2em;
line-height: normal;
} }
body { body {
@ -48,7 +57,7 @@ blockquote {
margin: 0; margin: 0;
} }
a:link { a:link, a:visited {
color: var(--darkest-color) color: var(--darkest-color)
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.