content: dead-simple-haskell
This commit is contained in:
parent
588a0d1480
commit
2ff3f15388
3
hie.yaml
Normal file
3
hie.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
cradle:
|
||||||
|
direct:
|
||||||
|
arguments: ["-pgmL", "markdown-unlit"]
|
BIN
public/static/content/slides/haskell-molecules/composition.png~
Normal file
BIN
public/static/content/slides/haskell-molecules/composition.png~
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 KiB |
BIN
public/static/content/slides/haskell-molecules/heavy-water.gif
Normal file
BIN
public/static/content/slides/haskell-molecules/heavy-water.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 423 KiB |
|
@ -55,16 +55,21 @@ const SPLIT_H = /\n-----\n/;
|
||||||
const SPLIT_V = /\n---\n/;
|
const SPLIT_V = /\n---\n/;
|
||||||
|
|
||||||
|
|
||||||
function wrapSection(content: string): string {
|
function wrapSection(animate: boolean, id: number) {
|
||||||
return `<section>${content}</section>`;
|
return (content: string): string => {
|
||||||
|
return animate
|
||||||
|
? `<section data-auto-animate data-auto-animate-id="${id}">${content}</section>`
|
||||||
|
: `<section>${content}</section>`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function render(text: string): string {
|
export function render(text: string, animate = false): string {
|
||||||
|
const wrapOuter = wrapSection(false, 0);
|
||||||
return text
|
return text
|
||||||
.split(SPLIT_H)
|
.split(SPLIT_H)
|
||||||
.map(stacks => stacks.split(SPLIT_V).map(slide => String(renderer.processSync(slide))))
|
.map(stacks => stacks.split(SPLIT_V).map(slide => String(renderer.processSync(slide))))
|
||||||
.map(stack => (stack.length > 1)
|
.map((stack, i) => (stack.length > 1)
|
||||||
? wrapSection(stack.map(wrapSection).join(''))
|
? wrapOuter(stack.map(wrapSection(animate, i)).join(''))
|
||||||
: wrapSection(stack[0]))
|
: wrapOuter(stack[0]))
|
||||||
.join('');
|
.join('');
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ export const collections = {
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
date: z.date(),
|
date: z.date(),
|
||||||
tags: z.array(z.string()).optional(),
|
tags: z.array(z.string()).optional(),
|
||||||
|
animate: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
wiki: defineCollection({
|
wiki: defineCollection({
|
||||||
|
|
658
src/content/slides/dead-simple-haskell/_DeadSimpleHaskell.lhs
Normal file
658
src/content/slides/dead-simple-haskell/_DeadSimpleHaskell.lhs
Normal file
|
@ -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
|
||||||
|
|
||||||
|
<interactive>: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
|
||||||
|
|
658
src/content/slides/dead-simple-haskell/index.md
Normal file
658
src/content/slides/dead-simple-haskell/index.md
Normal file
|
@ -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
|
||||||
|
|
||||||
|
<interactive>: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
|
||||||
|
|
|
@ -9,11 +9,16 @@ import { render } from '../../assets/reveal-ssr/markdown';
|
||||||
|
|
||||||
export async function getStaticPaths () {
|
export async function getStaticPaths () {
|
||||||
return (await getCollection('slides'))
|
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 { entry } = Astro.props;
|
||||||
const slides = render(entry.body);
|
|
||||||
|
const animate = entry.data.animate;
|
||||||
|
const slides = render(entry.body, animate);
|
||||||
---
|
---
|
||||||
|
|
||||||
<Base>
|
<Base>
|
||||||
|
@ -26,6 +31,7 @@ const slides = render(entry.body);
|
||||||
|
|
||||||
Reveal.initialize({
|
Reveal.initialize({
|
||||||
hash: true,
|
hash: true,
|
||||||
|
slideNumber: true,
|
||||||
plugins: [
|
plugins: [
|
||||||
Highlight,
|
Highlight,
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue