diff --git a/hie.yaml b/hie.yaml
new file mode 100644
index 0000000..4b37d9f
--- /dev/null
+++ b/hie.yaml
@@ -0,0 +1,3 @@
+cradle:
+ direct:
+ arguments: ["-pgmL", "markdown-unlit"]
diff --git a/public/static/content/slides/haskell-molecules/composition.png~ b/public/static/content/slides/haskell-molecules/composition.png~
new file mode 100644
index 0000000..8ce1980
Binary files /dev/null and b/public/static/content/slides/haskell-molecules/composition.png~ differ
diff --git a/public/static/content/slides/haskell-molecules/heavy-water.gif b/public/static/content/slides/haskell-molecules/heavy-water.gif
new file mode 100644
index 0000000..76de4a9
Binary files /dev/null and b/public/static/content/slides/haskell-molecules/heavy-water.gif differ
diff --git a/src/assets/reveal-ssr/markdown.ts b/src/assets/reveal-ssr/markdown.ts
index 0ddd2eb..5e094fe 100644
--- a/src/assets/reveal-ssr/markdown.ts
+++ b/src/assets/reveal-ssr/markdown.ts
@@ -26,7 +26,7 @@ const ESCAPED_CHARS: {[key: string]: string} = {
const REGEX_HL_LINES = /\[([\s\d,|-]*)\]/;
function transformCode(node: CodeNode, index: number, parent: Parent) {
if (!node.meta || !REGEX_HL_LINES.test(node.meta)) return;
-
+
const langtag = node.lang ? ` class="${node.lang}" ` : ''
const numbers = node.meta.match(REGEX_HL_LINES)![1];
const escaped = node.value.replace(/[&<>"']/g, match => ESCAPED_CHARS[match] || '');
@@ -55,16 +55,21 @@ const SPLIT_H = /\n-----\n/;
const SPLIT_V = /\n---\n/;
-function wrapSection(content: string): string {
- return ``;
+function wrapSection(animate: boolean, id: number) {
+ return (content: string): string => {
+ return animate
+ ? ``
+ : ``;
+ }
}
-export function render(text: string): string {
+export function render(text: string, animate = false): string {
+ const wrapOuter = wrapSection(false, 0);
return text
.split(SPLIT_H)
.map(stacks => stacks.split(SPLIT_V).map(slide => String(renderer.processSync(slide))))
- .map(stack => (stack.length > 1)
- ? wrapSection(stack.map(wrapSection).join(''))
- : wrapSection(stack[0]))
+ .map((stack, i) => (stack.length > 1)
+ ? wrapOuter(stack.map(wrapSection(animate, i)).join(''))
+ : wrapOuter(stack[0]))
.join('');
}
diff --git a/src/content/config.ts b/src/content/config.ts
index 2253689..0fbe30d 100644
--- a/src/content/config.ts
+++ b/src/content/config.ts
@@ -15,6 +15,7 @@ export const collections = {
title: z.string(),
date: z.date(),
tags: z.array(z.string()).optional(),
+ animate: z.boolean().optional(),
})
}),
wiki: defineCollection({
diff --git a/src/content/slides/dead-simple-haskell/_DeadSimpleHaskell.lhs b/src/content/slides/dead-simple-haskell/_DeadSimpleHaskell.lhs
new file mode 100644
index 0000000..cfd172f
--- /dev/null
+++ b/src/content/slides/dead-simple-haskell/_DeadSimpleHaskell.lhs
@@ -0,0 +1,658 @@
+---
+title: Dead simple Haskell
+date: 2024-01-11T21:21:41.263Z
+slug: dead-simple-haskell
+animate: true
+---
+
+# Dead simple Haskell
+
+![Haskell logo](/static/content/slides/haskell-molecules/haskell.png)
+
+-----
+
+## Haskell molecules
+
+-----
+
+### Atoms
+
+![atoms](/static/content/slides/haskell-molecules/atoms.png)
+
+---
+
+![atoms](/static/content/slides/haskell-molecules/atoms.png)
+
+```haskell
+data H = H -- hydrogen
+data O = O -- oxygen
+data C = C -- carbon
+```
+
+-----
+
+### Molecules
+
+![Atoms](/static/content/slides/haskell-molecules/molecules.png)
+
+---
+
+![Atoms](/static/content/slides/haskell-molecules/molecules.png)
+
+```haskell
+type H₂O = (H, O, H) -- water
+type O₂ = (O, O) -- oxygen (gas)
+type CO₂ = (O, C, O) -- carbon dioxide
+```
+
+-----
+
+### Reactions
+
+![Magic](/static/content/slides/haskell-molecules/magic.png)
+
+---
+
+![More magic](/static/content/slides/haskell-molecules/more-magic.png)
+
+---
+
+![More magic](/static/content/slides/haskell-molecules/more-magic.png)
+
+```haskell ignore
+makeWater :: H -> H -> O -> H₂O
+```
+```haskell ignore
+makeOxygen :: O -> O -> O₂
+```
+```haskell ignore
+burnOxygen :: C -> O₂ -> CO₂
+```
+
+---
+
+```haskell
+makeWater :: H -> H -> O -> H₂O
+```
+```haskell
+makeWater h1 h2 o = (h1, o, h2)
+```
+~
+
+```haskell
+makeOxygen :: O -> O -> O₂
+```
+```haskell
+makeOxygen o1 o2 = (o1, o2)
+```
+~
+
+```haskell
+burnOxygen :: C -> O₂ -> CO₂
+```
+```haskell
+burnOxygen c (o1, o2) = (o1, c, o2)
+```
+
+-----
+
+### `.` `$`
+
+![Plumbing](/static/content/slides/haskell-molecules/plumbing.png)
+
+---
+
+![Partial application](/static/content/slides/haskell-molecules/partial.png)
+
+```haskell ignore
+λ> :type makeOxygen
+makeOxygen :: O -> O -> O₂
+```
+```haskell ignore
+λ> :type makeOxygen O
+makeOxygen O :: O -> O₂
+```
+```haskell ignore
+λ> :type makeOxygen O O
+makeOxygen O O :: O₂
+```
+
+---
+
+![Combustion](/static/content/slides/haskell-molecules/combustion.png)
+
+```haskell ignore
+λ> :type burnOxygen
+burnOxygen :: C -> O₂ -> CO₂
+```
+```haskell ignore
+λ> :type burnOxygen C
+burnOxygen C :: O₂ -> CO₂
+```
+```haskell ignore
+λ> :type burnOxygen C (O, O)
+burnOxygen C O₂ :: CO₂
+```
+
+---
+
+
+![Two functions](/static/content/slides/haskell-molecules/two-fs.png)
+
+```haskell
+f1 :: O -> O₂
+f1 = makeOxygen O
+
+f2 :: O₂ -> CO₂
+f2 = burnOxygen C
+```
+
+---
+
+![Composition](/static/content/slides/haskell-molecules/composition.png)
+
+
+```haskell
+f3 = f2 . f1
+```
+
+---
+
+![Composition2](/static/content/slides/haskell-molecules/composition2.png)
+
+```haskell
+f3 :: O -> CO₂
+```
+
+```haskell ignore
+f1 :: { O -> O₂ }
+f2 :: [ O₂ -> CO₂ ]
+f3 :: {O -> [ O₂ } -> CO₂ ]
+f3 :: O -> CO₂
+```
+
+---
+
+```haskell ignore
+f3' o = f2 . f1 o
+```
+
+```scala
+Diagnostics:
+1. • Couldn't match type: (O, O)
+ with: a -> O₂
+ Expected: a -> O₂
+ Actual: O₂
+ • Possible cause: ‘f1’ is applied to too many arguments
+ In the second argument of ‘(.)’, namely ‘f1 o’
+ In the expression: f2 . f1 o
+ In an equation for ‘f3'’: f3' o = f2 . f1 o
+ • Relevant bindings include
+ f3' :: O -> a -> CO₂
+ (bound at Script.hs:112:1) [-Wdeferred-type-errors]
+```
+
+---
+
+![Composition3](/static/content/slides/haskell-molecules/composition3.png)
+
+```haskell ignore
+f3' o = f2 . f1 o
+```
+
+---
+
+![Funnel](/static/content/slides/haskell-molecules/funnel.png)
+
+```haskell ignore
+f3' o = f2 . f1 $ o
+
+-- OR
+
+f3' o = f2 $ f1 o
+```
+
+---
+
+```haskell ignore
+infixr 9 .
+(.) :: (b -> c) -> (a -> b) -> (a -> c)
+(f . g) x = f (g x)
+
+infixr 0 $
+($) :: (a -> b) -> a -> b
+f $ x = f x
+```
+
+-----
+
+## Isotopes
+
+![Heavy water](/static/content/slides/haskell-molecules/heavy-water.gif)
+
+---
+
+![Isotopes](/static/content/slides/haskell-molecules/isotopes.png)
+
+---
+
+```haskell
+data H'
+ = H¹-- protium
+ | H²-- deuterium
+ | H³-- tritium
+
+type H2O' = (H', O, H') -- water
+```
+
+```haskell
+makeWater' :: H' -> H' -> O -> H2O'
+makeWater' h1 h2 o = (h1, o, h2)
+```
+
+---
+
+### Algebra
+
+How many values inhibit each of these?
+
+Type | Possibilities
+---------- | -------------
+`()` | ?
+`O` | ?
+`H'` | ?
+`(H', H')` | ?
+
+---
+
+`()`
+
+---
+
+`()`
+
+1
+
+`()`
+
+---
+
+`O`
+
+---
+
+`O`
+
+1
+
+`O`
+
+---
+
+`H'`
+
+---
+
+`H'`
+
+3
+
+`H¹` `H²` `H³`
+
+---
+
+`(H', H')`
+
+---
+
+`(H', H')`
+
+9
+
+`(H¹, H¹)` `(H¹, H²)` `(H¹, H³)`
+
+`(H², H¹)` `(H², H²)` `(H², H³)`
+
+`(H³, H¹)` `(H³, H²)` `(H³, H³)`
+
+---
+
+`(H', Bool)`
+
+---
+
+`(H', Bool)`
+
+6
+
+`(H¹, True)` `(H¹, False)`
+
+`(H², True)` `(H², False)`
+
+`(H³, True)` `(H³, False)`
+
+---
+
+Type | Inhibitants
+---------- | -----------
+`()` | 1
+`Bool` | 2
+`H'` | 3
+`A` | a
+`B` | b
+`(A, B)` | a × b
+`A` \| `B` | a + b
+
+---
+
+Product types Π
+
+Type | Inhibitants
+---------- | -----------
+() | 1
+Bool | 2
+((), Bool) | 1 × 2 = 2
+(H', Bool) | 3 × 2 = 6
+
+```haskell ignore
+data Pair a b = Pair a b
+```
+
+---
+
+```haskell ignore
+type Pair a b = (a, b)
+```
+
+```haskell ignore
+data Pair a b = Pair a b
+```
+
+```haskell ignore
+data Pair a b = Pair
+ { fieldA :: a
+ , fieldB :: b
+ }
+```
+
+---
+
+Sum types Σ
+
+Type | Inhibitants
+---------- | -----------
+() | 1
+Bool | 2
+() | Bool | 1 + 2 = 3
+H' | Bool | 3 + 2 = 5
+
+```haskell ignore
+data Either a b = Left a | Right b
+```
+
+---
+
+Why not both?
+
+---
+
+Why not both?
+
+```haskell ignore
+data Crazy a b
+ = CrazyA a
+ | CrazyB b
+ | Both a b
+ | Neither
+```
+
+---
+
+```haskell ignore
+data Crazy a b
+ = CrazyA a
+ | CrazyB b
+ | Both a b
+ | Neither
+```
+
+Member | Inhibitants
+---------- | -----------
+`CrazyA a` | a
+`CrazyB b` | b
+`Both a b` | a × b
+`Neither` | 1
+Σ | a + b + a × b + 1
+
+---
+
+Can there be a "0"?
+
+---
+
+Can there be a "0"?
+
+Yes
+
+```haskell ignore
+Crazy Void ()
+ = CrazyA Void
+ | CrazyB ()
+ | Both Void ()
+ | Neither
+```
+
+Σ = 0 + 1 + 0 × 1 + 1 = 2
+
+
+-----
+
+### Traits
+
+![Neon colors](/static/content/slides/haskell-molecules/neon.png)
+
+---
+
+Element name | Color
+------------ | ------
+Helium | orange
+Neon | red
+Argon | lavender
+Krypton | white
+Xenon | blue
+Radon | red
+
+---
+
+```haskell
+data He = He -- Helium
+data Ne = Ne -- Neon
+data Ar = Ar -- Argon
+data Kr = Kr -- Krypton
+data Xe = Xe -- Xenon
+data Rn = Rn -- Radon
+```
+
+---
+
+How to convert noble gases to color?
+
+```haskell ignore
+toColor :: ? -> String
+```
+
+---
+
+What about allowing everything in?
+
+```haskell ignore
+toColor :: a -> String
+toColor a
+ | a == He = "orange"
+ | a == Ne = "red"
+ | otherwise = undefined
+
+-- ???
+_ = toColor "anything in"
+_ = toColor 1234
+```
+
+---
+
+What about treating noble gases as a sum type?
+
+```haskell ignore
+data Noble
+ = He
+ | Ne
+ | Ar
+ | Kr
+ | Xe
+ | Rn
+```
+
+---
+
+`a -> String`
+
+^
+
+???
+
+^
+
+`Noble -> String`
+
+---
+
+```haskell
+class Noble a where
+ toColor :: a -> String
+```
+
+~
+
+```haskell
+instance Noble He where
+ toColor _ = "orange"
+
+instance Noble Ne where
+ toColor _ = "red"
+
+instance Noble Ar where
+ toColor _ = "lavender"
+```
+
+---
+
+Works:
+
+```haskell ignore
+λ> toColor He
+"orange"
+λ> toColor Ne
+"red"
+```
+
+Doesn't work:
+
+```haskell ignore
+λ> toColor C
+
+:6:1: error:
+ • No instance for (Noble C) arising from a use of ‘toColor’
+ • In the expression: toColor C
+ In an equation for ‘it’: it = toColor C
+```
+
+---
+
+```haskell
+mixNoble :: (Noble n1, Noble n2) => n1 -> n2 -> String
+mixNoble n1 n2 = toColor n1 <> "-" <> toColor n2
+```
+
+```haskell ignore
+λ> mixNoble He Ne
+"orange-red"
+```
+
+-----
+
+## Shrodinger's cat
+
+(A change of topic)
+
+---
+
+```haskell
+data Box a
+ = Has a
+ | Empty
+```
+
+---
+
+```haskell
+class Mappable box where
+ map' :: box a -> box b
+```
+
+---
+
+```haskell
+class Appliable box where
+ wrap :: a -> box a
+ apply' :: box (a -> b) -> box a -> box b
+```
+
+---
+
+```haskell
+class Chainable box where
+ chain :: box a -> (a -> box b) -> box b
+```
+
+-----
+
+In fact it all already exists.
+
+![This was all dream](/static/content/slides/haskell-molecules/_cave.jpg)
+
+---
+
+What's a `Mappable`?
+
+---
+
+![It's a Functor](/static/content/slides/haskell-molecules/scoobydoo.jpg)
+
+---
+
+What's a `Appliable`?
+
+---
+
+![It's a Functor](/static/content/slides/haskell-molecules/scoobydoo.jpg)
+
+---
+
+What's a `Chainable`?
+
+---
+
+![It's a Functor](/static/content/slides/haskell-molecules/scoobydoo.jpg)
+
+---
+
+## Fun with monadic parsing
+
+
+---
+
+## More here:
+
+- **Learn You a Haskell for Great Good!** by Miran Lipovaca
+- **Programming in Haskell - 2nd Edition** by Graham Hutton
+- **Effective Haskell** by Rebecca Skinner
+
diff --git a/src/content/slides/dead-simple-haskell/index.md b/src/content/slides/dead-simple-haskell/index.md
new file mode 100644
index 0000000..cfd172f
--- /dev/null
+++ b/src/content/slides/dead-simple-haskell/index.md
@@ -0,0 +1,658 @@
+---
+title: Dead simple Haskell
+date: 2024-01-11T21:21:41.263Z
+slug: dead-simple-haskell
+animate: true
+---
+
+# Dead simple Haskell
+
+![Haskell logo](/static/content/slides/haskell-molecules/haskell.png)
+
+-----
+
+## Haskell molecules
+
+-----
+
+### Atoms
+
+![atoms](/static/content/slides/haskell-molecules/atoms.png)
+
+---
+
+![atoms](/static/content/slides/haskell-molecules/atoms.png)
+
+```haskell
+data H = H -- hydrogen
+data O = O -- oxygen
+data C = C -- carbon
+```
+
+-----
+
+### Molecules
+
+![Atoms](/static/content/slides/haskell-molecules/molecules.png)
+
+---
+
+![Atoms](/static/content/slides/haskell-molecules/molecules.png)
+
+```haskell
+type H₂O = (H, O, H) -- water
+type O₂ = (O, O) -- oxygen (gas)
+type CO₂ = (O, C, O) -- carbon dioxide
+```
+
+-----
+
+### Reactions
+
+![Magic](/static/content/slides/haskell-molecules/magic.png)
+
+---
+
+![More magic](/static/content/slides/haskell-molecules/more-magic.png)
+
+---
+
+![More magic](/static/content/slides/haskell-molecules/more-magic.png)
+
+```haskell ignore
+makeWater :: H -> H -> O -> H₂O
+```
+```haskell ignore
+makeOxygen :: O -> O -> O₂
+```
+```haskell ignore
+burnOxygen :: C -> O₂ -> CO₂
+```
+
+---
+
+```haskell
+makeWater :: H -> H -> O -> H₂O
+```
+```haskell
+makeWater h1 h2 o = (h1, o, h2)
+```
+~
+
+```haskell
+makeOxygen :: O -> O -> O₂
+```
+```haskell
+makeOxygen o1 o2 = (o1, o2)
+```
+~
+
+```haskell
+burnOxygen :: C -> O₂ -> CO₂
+```
+```haskell
+burnOxygen c (o1, o2) = (o1, c, o2)
+```
+
+-----
+
+### `.` `$`
+
+![Plumbing](/static/content/slides/haskell-molecules/plumbing.png)
+
+---
+
+![Partial application](/static/content/slides/haskell-molecules/partial.png)
+
+```haskell ignore
+λ> :type makeOxygen
+makeOxygen :: O -> O -> O₂
+```
+```haskell ignore
+λ> :type makeOxygen O
+makeOxygen O :: O -> O₂
+```
+```haskell ignore
+λ> :type makeOxygen O O
+makeOxygen O O :: O₂
+```
+
+---
+
+![Combustion](/static/content/slides/haskell-molecules/combustion.png)
+
+```haskell ignore
+λ> :type burnOxygen
+burnOxygen :: C -> O₂ -> CO₂
+```
+```haskell ignore
+λ> :type burnOxygen C
+burnOxygen C :: O₂ -> CO₂
+```
+```haskell ignore
+λ> :type burnOxygen C (O, O)
+burnOxygen C O₂ :: CO₂
+```
+
+---
+
+
+![Two functions](/static/content/slides/haskell-molecules/two-fs.png)
+
+```haskell
+f1 :: O -> O₂
+f1 = makeOxygen O
+
+f2 :: O₂ -> CO₂
+f2 = burnOxygen C
+```
+
+---
+
+![Composition](/static/content/slides/haskell-molecules/composition.png)
+
+
+```haskell
+f3 = f2 . f1
+```
+
+---
+
+![Composition2](/static/content/slides/haskell-molecules/composition2.png)
+
+```haskell
+f3 :: O -> CO₂
+```
+
+```haskell ignore
+f1 :: { O -> O₂ }
+f2 :: [ O₂ -> CO₂ ]
+f3 :: {O -> [ O₂ } -> CO₂ ]
+f3 :: O -> CO₂
+```
+
+---
+
+```haskell ignore
+f3' o = f2 . f1 o
+```
+
+```scala
+Diagnostics:
+1. • Couldn't match type: (O, O)
+ with: a -> O₂
+ Expected: a -> O₂
+ Actual: O₂
+ • Possible cause: ‘f1’ is applied to too many arguments
+ In the second argument of ‘(.)’, namely ‘f1 o’
+ In the expression: f2 . f1 o
+ In an equation for ‘f3'’: f3' o = f2 . f1 o
+ • Relevant bindings include
+ f3' :: O -> a -> CO₂
+ (bound at Script.hs:112:1) [-Wdeferred-type-errors]
+```
+
+---
+
+![Composition3](/static/content/slides/haskell-molecules/composition3.png)
+
+```haskell ignore
+f3' o = f2 . f1 o
+```
+
+---
+
+![Funnel](/static/content/slides/haskell-molecules/funnel.png)
+
+```haskell ignore
+f3' o = f2 . f1 $ o
+
+-- OR
+
+f3' o = f2 $ f1 o
+```
+
+---
+
+```haskell ignore
+infixr 9 .
+(.) :: (b -> c) -> (a -> b) -> (a -> c)
+(f . g) x = f (g x)
+
+infixr 0 $
+($) :: (a -> b) -> a -> b
+f $ x = f x
+```
+
+-----
+
+## Isotopes
+
+![Heavy water](/static/content/slides/haskell-molecules/heavy-water.gif)
+
+---
+
+![Isotopes](/static/content/slides/haskell-molecules/isotopes.png)
+
+---
+
+```haskell
+data H'
+ = H¹-- protium
+ | H²-- deuterium
+ | H³-- tritium
+
+type H2O' = (H', O, H') -- water
+```
+
+```haskell
+makeWater' :: H' -> H' -> O -> H2O'
+makeWater' h1 h2 o = (h1, o, h2)
+```
+
+---
+
+### Algebra
+
+How many values inhibit each of these?
+
+Type | Possibilities
+---------- | -------------
+`()` | ?
+`O` | ?
+`H'` | ?
+`(H', H')` | ?
+
+---
+
+`()`
+
+---
+
+`()`
+
+1
+
+`()`
+
+---
+
+`O`
+
+---
+
+`O`
+
+1
+
+`O`
+
+---
+
+`H'`
+
+---
+
+`H'`
+
+3
+
+`H¹` `H²` `H³`
+
+---
+
+`(H', H')`
+
+---
+
+`(H', H')`
+
+9
+
+`(H¹, H¹)` `(H¹, H²)` `(H¹, H³)`
+
+`(H², H¹)` `(H², H²)` `(H², H³)`
+
+`(H³, H¹)` `(H³, H²)` `(H³, H³)`
+
+---
+
+`(H', Bool)`
+
+---
+
+`(H', Bool)`
+
+6
+
+`(H¹, True)` `(H¹, False)`
+
+`(H², True)` `(H², False)`
+
+`(H³, True)` `(H³, False)`
+
+---
+
+Type | Inhibitants
+---------- | -----------
+`()` | 1
+`Bool` | 2
+`H'` | 3
+`A` | a
+`B` | b
+`(A, B)` | a × b
+`A` \| `B` | a + b
+
+---
+
+Product types Π
+
+Type | Inhibitants
+---------- | -----------
+() | 1
+Bool | 2
+((), Bool) | 1 × 2 = 2
+(H', Bool) | 3 × 2 = 6
+
+```haskell ignore
+data Pair a b = Pair a b
+```
+
+---
+
+```haskell ignore
+type Pair a b = (a, b)
+```
+
+```haskell ignore
+data Pair a b = Pair a b
+```
+
+```haskell ignore
+data Pair a b = Pair
+ { fieldA :: a
+ , fieldB :: b
+ }
+```
+
+---
+
+Sum types Σ
+
+Type | Inhibitants
+---------- | -----------
+() | 1
+Bool | 2
+() | Bool | 1 + 2 = 3
+H' | Bool | 3 + 2 = 5
+
+```haskell ignore
+data Either a b = Left a | Right b
+```
+
+---
+
+Why not both?
+
+---
+
+Why not both?
+
+```haskell ignore
+data Crazy a b
+ = CrazyA a
+ | CrazyB b
+ | Both a b
+ | Neither
+```
+
+---
+
+```haskell ignore
+data Crazy a b
+ = CrazyA a
+ | CrazyB b
+ | Both a b
+ | Neither
+```
+
+Member | Inhibitants
+---------- | -----------
+`CrazyA a` | a
+`CrazyB b` | b
+`Both a b` | a × b
+`Neither` | 1
+Σ | a + b + a × b + 1
+
+---
+
+Can there be a "0"?
+
+---
+
+Can there be a "0"?
+
+Yes
+
+```haskell ignore
+Crazy Void ()
+ = CrazyA Void
+ | CrazyB ()
+ | Both Void ()
+ | Neither
+```
+
+Σ = 0 + 1 + 0 × 1 + 1 = 2
+
+
+-----
+
+### Traits
+
+![Neon colors](/static/content/slides/haskell-molecules/neon.png)
+
+---
+
+Element name | Color
+------------ | ------
+Helium | orange
+Neon | red
+Argon | lavender
+Krypton | white
+Xenon | blue
+Radon | red
+
+---
+
+```haskell
+data He = He -- Helium
+data Ne = Ne -- Neon
+data Ar = Ar -- Argon
+data Kr = Kr -- Krypton
+data Xe = Xe -- Xenon
+data Rn = Rn -- Radon
+```
+
+---
+
+How to convert noble gases to color?
+
+```haskell ignore
+toColor :: ? -> String
+```
+
+---
+
+What about allowing everything in?
+
+```haskell ignore
+toColor :: a -> String
+toColor a
+ | a == He = "orange"
+ | a == Ne = "red"
+ | otherwise = undefined
+
+-- ???
+_ = toColor "anything in"
+_ = toColor 1234
+```
+
+---
+
+What about treating noble gases as a sum type?
+
+```haskell ignore
+data Noble
+ = He
+ | Ne
+ | Ar
+ | Kr
+ | Xe
+ | Rn
+```
+
+---
+
+`a -> String`
+
+^
+
+???
+
+^
+
+`Noble -> String`
+
+---
+
+```haskell
+class Noble a where
+ toColor :: a -> String
+```
+
+~
+
+```haskell
+instance Noble He where
+ toColor _ = "orange"
+
+instance Noble Ne where
+ toColor _ = "red"
+
+instance Noble Ar where
+ toColor _ = "lavender"
+```
+
+---
+
+Works:
+
+```haskell ignore
+λ> toColor He
+"orange"
+λ> toColor Ne
+"red"
+```
+
+Doesn't work:
+
+```haskell ignore
+λ> toColor C
+
+:6:1: error:
+ • No instance for (Noble C) arising from a use of ‘toColor’
+ • In the expression: toColor C
+ In an equation for ‘it’: it = toColor C
+```
+
+---
+
+```haskell
+mixNoble :: (Noble n1, Noble n2) => n1 -> n2 -> String
+mixNoble n1 n2 = toColor n1 <> "-" <> toColor n2
+```
+
+```haskell ignore
+λ> mixNoble He Ne
+"orange-red"
+```
+
+-----
+
+## Shrodinger's cat
+
+(A change of topic)
+
+---
+
+```haskell
+data Box a
+ = Has a
+ | Empty
+```
+
+---
+
+```haskell
+class Mappable box where
+ map' :: box a -> box b
+```
+
+---
+
+```haskell
+class Appliable box where
+ wrap :: a -> box a
+ apply' :: box (a -> b) -> box a -> box b
+```
+
+---
+
+```haskell
+class Chainable box where
+ chain :: box a -> (a -> box b) -> box b
+```
+
+-----
+
+In fact it all already exists.
+
+![This was all dream](/static/content/slides/haskell-molecules/_cave.jpg)
+
+---
+
+What's a `Mappable`?
+
+---
+
+![It's a Functor](/static/content/slides/haskell-molecules/scoobydoo.jpg)
+
+---
+
+What's a `Appliable`?
+
+---
+
+![It's a Functor](/static/content/slides/haskell-molecules/scoobydoo.jpg)
+
+---
+
+What's a `Chainable`?
+
+---
+
+![It's a Functor](/static/content/slides/haskell-molecules/scoobydoo.jpg)
+
+---
+
+## Fun with monadic parsing
+
+
+---
+
+## More here:
+
+- **Learn You a Haskell for Great Good!** by Miran Lipovaca
+- **Programming in Haskell - 2nd Edition** by Graham Hutton
+- **Effective Haskell** by Rebecca Skinner
+
diff --git a/src/pages/slides/[...slug].astro b/src/pages/slides/[...slug].astro
index c611ea8..bae3311 100644
--- a/src/pages/slides/[...slug].astro
+++ b/src/pages/slides/[...slug].astro
@@ -9,11 +9,16 @@ import { render } from '../../assets/reveal-ssr/markdown';
export async function getStaticPaths () {
return (await getCollection('slides'))
- .map(entry => ({params: {slug: entry.slug}, props: {entry}}));
+ .map(entry => ({
+ params: { slug: entry.slug },
+ props: { entry }
+ }));
}
const { entry } = Astro.props;
-const slides = render(entry.body);
+
+const animate = entry.data.animate;
+const slides = render(entry.body, animate);
---
@@ -26,6 +31,7 @@ const slides = render(entry.body);
Reveal.initialize({
hash: true,
+ slideNumber: true,
plugins: [
Highlight,
]