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 `
${content}
`; +function wrapSection(animate: boolean, id: number) { + return (content: string): string => { + return animate + ? `
${content}
` + : `
${content}
`; + } } -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, ]