spout: s17

This commit is contained in:
mehbark 2026-09-01 01:05:52 -04:00
parent 2748bc5640
commit f932215a0d
Signed by: mbk
GPG key ID: E333EC1335FFCCDB
3 changed files with 66 additions and 68 deletions

View file

@ -1,58 +0,0 @@
---
title: "Monads: Why and how"
description: I could not repress the urge to make a monad explainer any longer. Did you know that a monad is a monoid in the category of endofunctors?
tags: post,short,haskell
date: 2026-05-06 01:20:10 -5
---
I acknowledge that [the world wide web has one hundred trillion monad explainers.](https://wiki.haskell.org/Monad_tutorials_timeline)
![Chart titled "Number of known monad tutorials. It grew from zero in 1991 to fifteenish in 2005 before increasing in speed and ending at about 120 in 2023](https://wiki.haskell.org/wikiupload/2/23/Monad-tutorials-chart.png)
## Why monads
In the land of Haskell and friends, we love referential transparency.
We greatly appreciate that
```haskell
let x = 1 in x + x
```
will always have the same result as
```haskell
1 + 1
```
In languages where (almost) no functions have unmarked side-effects, like Haskell, you can even be confident that
```haskell
let x = f y in x + x
```
is the same as
```haskell
(f y) + (f y)
```
This is a truly excellent property to have, but it causes some problems when your program starts interacting with the world.
Aside from referential transparency, we don't want to fix evaluation order if we don't have to;
giving the compiler more freedom to reorder evaluation lets it perform more optimizations.
And we always want more optimizations.
But, quite often, we *need* things to happen in a specific order.
Monads let us do two things:
1. Order operations
2. Use past results to decide what to do next
## How monads
Easy:
```haskell
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
pure :: a -> m a
```
`>>=`, pronounced `bind`, gives us ordering and lets us use past results to decide what to do next.
The fact that it gives us ordering is made more clear if we define `>>`, which ignores its result:
```haskell
(>>) :: m a -> m b -> m b
a >> b = a >>= \_ -> b
```

View file

@ -1,9 +1,9 @@
<!doctype html>
<html><head><title>spout</title>
<meta charset="UTF-8">
<meta charset="UTF-8">
<meta content="spout" property="og:title" />
<meta content="i post html" property="og:description" />
<meta content="https://terezi.pyrope.net/spout" property="og:url" />
<meta content="https://terezi.pyrope.net/spout" property="og:url" />
<meta content="#008282" data-react-helmet="true" name="theme-color" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@ -144,6 +144,12 @@ h2 {
<body>
<h1 style="margin: 1rem">spout: reverse-chron html pieces by <a href="https://terezi.pyrope.net">mehbark</a></h1>
<article id="s18">
<h1><a href="#s18">#</a> variable weight noodling</h1>
<p>warning: smoothly changing fonts that may be a bit nauseating. also uses google fonts (shame).</p>
<p><a href="./variable-font-noodling.html">enter if you dare</a></p>
</article>
<article id="s17">
<h1><a href="#s17">#</a> graphing with sign-changes</h1>
<p>I had somehow never heard of this canonical graphing technique until watching <a href="https://www.youtube.com/watch?v=YJJk0iLJ4Ks">this video about a 3d graphing calculator in minecraft</a></p>
@ -297,7 +303,7 @@ this version is unproven, <a href="https://www.gavalas.dev/blog/spigot-algorithm
fair warning: especially with larger batch sizes, this is liable to freeze up the tab. tread carefully!
</p>
<pre id=s12-output style="overflow: auto; height: 36ch; width: 100%; word-break: break-all; white-space: pre-wrap;">
3.</pre>
3.</pre>
<button onclick='
(() => {
if (this.interval) {
@ -398,7 +404,7 @@ let b = +batch.value;
let [ins, tot] = [+inside.innerText, +total.innerText];
if (!(n > 0)) {
alert(`come on, ${n} samples?`);
return;
return;
}
let ctx = canvas.getContext("2d");
setTimeout(function sample() {
@ -414,7 +420,7 @@ setTimeout(function sample() {
if (!n--) break;
}
inside.innerText = ins;
total.innerText = tot;
best.innerText = 4 * ins/tot;
@ -426,7 +432,7 @@ setTimeout(function sample() {
<p>this is thoroughly ingrained in my brain, but i hope it's still fairly intuitive for others.
i like how the boundary becomes more clear with more samples, it makes the accuracy more understandable <abbr title="in my opinion">imo</abbr>
</article>
<article id="s9">
<h1><a href="#s9">#</a> apropos of <a href="#s7">s7</a></h1>
<p>i may not be stupid!
@ -443,7 +449,7 @@ that might be here! in ! th efuture</p>
this.innerText = "stop D:";
let [lhs, rhs, canvas, samples] = elems(9, "lhs rhs canvas samples");
let ctx = canvas.getContext("2d");
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
let f = eval(`(x, y) => {with (Math) {return abs((${lhs.value}) - (${rhs.value}))}}`);
let guys = [];
@ -609,7 +615,7 @@ the first time was on <code>about:blank</code> in canvas, and the second time wa
let order = +document.getElementById("s7-deriv").innerText;
for (let i = 0; i < order; i++) f = deriv(f);
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
ctx.clearRect(0, 0, 1000, 1000);
for (let x = x0; x <= x1; x += (x1 - x0)/1200) {
ctx.fillRect(x.map(x0, x1, 0, 300), f(x).map(y0, y1, 300, 0), 1, 1);
@ -633,7 +639,7 @@ the first time was on <code>about:blank</code> in canvas, and the second time wa
let ctx = document.getElementById("s6-canvas").getContext("2d");
ctx.fillStyle = "#76a6e4";
let f = eval(`(x, y) => {with (Math) {return y - (${this.value})}}`);
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
let guys = [];
for (let x = x0; x <= x1; x += (x1 - x0)/600) {
guys.push({x, y: 0, dy: 0.1, lastDiff: 1});
@ -679,7 +685,7 @@ the first time was on <code>about:blank</code> in canvas, and the second time wa
<article id="s5">
<h1><a href="#s5">#</a> why spout</h1>
<p>i have <a href="https://b.pyrope.net">my blog</a> for when i want to make really legit-looking posts.
it's made with <a href="https://docs.racket-lang.org/pollen/">pollen</a>, which is great, and i can make even the most lame posts (currently all of the posts) look very nice.
it's made with <a href="https://docs.racket-lang.org/pollen/">pollen</a>, which is great, and i can make even the most lame posts (currently all of the posts) look very nice.
however, there's a whole build system, the book is a program after all, a lot of things have to happen to make a post there happen. so i wanted something smaller. micro, if you will.
hence, spout! i just write some html (which, tbh, i kinda prefer to markdown) with no restrictions. ssh, edit file, save file, done. it's great! it <em>really</em> needs an RSS feed, though…
</article>

View file

@ -0,0 +1,50 @@
<!doctype html>
<html>
<head>
<title>variable font weights</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible+Next:wght@200..800&family=Google+Sans+Flex:opsz,wght@6..144,1..1000&family=Inter:opsz,wght@14..32,100..900&family=JetBrains+Mono:wght@100..800&family=Montserrat:wght@100..900&family=Open+Sans:wght@300..800&family=Playfair+Display:wght@400..900&family=Source+Code+Pro:wght@200..900&display=swap" rel="stylesheet">
<style>
ul {
list-decoration: none;
}
li {
font-optical-sizing: auto;
font-size: 10rem;
text-align: center;
animation: vary 6.7s linear infinite alternate;
}
@keyframes vary {
from {
font-weight: var(--min);
}
to {
font-weight: var(--max);
}
}
</style>
<script>
document.addEventListener("DOMContentLoaded", () => document.querySelectorAll("li").forEach(li => {
const family = li.style.fontFamily.replaceAll('"', "");
const min = li.style.getPropertyValue("--min");
const max = li.style.getPropertyValue("--max");
li.title = `${family} (${min}-${max})`
}));
</script>
</head>
<body>
<ul>
<li style="--min: 200; --max: 800; font-family: 'Atkinson Hyperlegible Next'">Variable</li>
<li style="--min: 1; --max: 1000; font-family: 'Google Sans Flex'">Variable</li>
<li style="--min: 300; --max: 800; font-family: 'Open Sans'">Variable</li>
<li style="--min: 100; --max: 900; font-family: 'Inter'">Variable</li>
<li style="--min: 100; --max: 900; font-family: 'Montserrat'">Variable</li>
<li style="--min: 400; --max: 900; font-family: 'Playfair Display'">Variable</li>
<li style="--min: 200; --max: 900; font-family: 'Source Code Pro'">Variable</li>
<li style="--min: 100; --max: 800; font-family: 'JetBrains Mono'">Variable</li>
</ul>
</body>
</html>