2024-02-04 01:00:25 +01:00
|
|
|
|
---
|
|
|
|
|
title: Dead simple Haskell
|
|
|
|
|
date: 2024-01-11T21:21:41.263Z
|
|
|
|
|
slug: dead-simple-haskell
|
|
|
|
|
animate: true
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# Dead simple Haskell
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Haskell logo](haskell.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
## Haskell molecules
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
### Atoms
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![atoms](atoms.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![atoms](atoms.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
data H = H -- hydrogen
|
|
|
|
|
data O = O -- oxygen
|
|
|
|
|
data C = C -- carbon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
### Molecules
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Atoms](molecules.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Atoms](molecules.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
type H₂O = (H, O, H) -- water
|
|
|
|
|
type O₂ = (O, O) -- oxygen (gas)
|
|
|
|
|
type CO₂ = (O, C, O) -- carbon dioxide
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
### Reactions
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Magic](magic.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![More magic](more-magic.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![More magic](more-magic.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```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)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
### `.` `$`
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Plumbing](plumbing.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Partial application](partial.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```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₂
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Combustion](combustion.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```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₂
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Two functions](two-fs.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
f1 :: O -> O₂
|
|
|
|
|
f1 = makeOxygen O
|
|
|
|
|
|
|
|
|
|
f2 :: O₂ -> CO₂
|
|
|
|
|
f2 = burnOxygen C
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Composition](composition.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
f3 = f2 . f1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Composition2](composition2.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```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]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Composition3](composition3.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
f3' o = f2 . f1 o
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Funnel](funnel.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```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
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Heavy water](heavy-water.gif)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Isotopes](isotopes.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```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
|
2024-02-04 15:34:58 +01:00
|
|
|
|
() \| Bool | 1 + 2 = 3
|
|
|
|
|
H' \| Bool | 3 + 2 = 5
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
```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
|
|
|
|
|
|
2024-02-05 22:21:39 +01:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
How do lists fit into this?
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
How do lists fit into this?
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
data List a
|
|
|
|
|
= Nil
|
|
|
|
|
| Cons a (List a)
|
|
|
|
|
```
|
|
|
|
|
```haskell
|
|
|
|
|
-- [1, 2, 3] or 1 : 2 : 3 []
|
|
|
|
|
list1 = Cons 1 (Cons 2 (Cons 3 Nil))
|
|
|
|
|
-- []
|
|
|
|
|
list2 = Nil
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
data List a
|
|
|
|
|
= Nil
|
|
|
|
|
| Cons a (List a)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
x = 1 + a * x
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
data List a
|
|
|
|
|
= Nil
|
|
|
|
|
| Cons a (List a)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
x = 1 + a * x
|
|
|
|
|
x = 1 + a * (1 + a * x)
|
|
|
|
|
x = 1 + a * (1 + a * (1 + a * (...)))
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
data List a
|
|
|
|
|
= Nil
|
|
|
|
|
| Cons a (List a)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
x = 1 + a * x
|
|
|
|
|
x = 1 + a * (1 + a * x)
|
|
|
|
|
x = 1 + a * (1 + a * (1 + a * (...)))
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
x = 1 + a + a² + a³ + a⁴ + a⁵ + ...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
data List a
|
|
|
|
|
= Nil
|
|
|
|
|
| Cons a (List a)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
x = 1 + a * x
|
|
|
|
|
x = 1 + a * (1 + a * x)
|
|
|
|
|
x = 1 + a * (1 + a * (1 + a * (...)))
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
x = 1 + a + a² + a³ + a⁴ + a⁵ + ...
|
|
|
|
|
```
|
|
|
|
|
```haskell ignore
|
|
|
|
|
data List a = () | (a) | (a, a) | (a, a, a) | ...
|
|
|
|
|
```
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
### Traits
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Neon colors](neon.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat in a box](cat.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat in a box](cat.png)
|
2024-02-04 13:16:07 +01:00
|
|
|
|
|
2024-02-04 01:00:25 +01:00
|
|
|
|
```haskell
|
|
|
|
|
data Box a
|
|
|
|
|
= Has a
|
|
|
|
|
| Empty
|
2024-02-04 13:16:07 +01:00
|
|
|
|
deriving Show
|
2024-02-04 01:00:25 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Map](map.png)
|
2024-02-04 13:16:07 +01:00
|
|
|
|
|
2024-02-05 22:21:39 +01:00
|
|
|
|
```haskell
|
|
|
|
|
data Cat = Cat String deriving Show
|
|
|
|
|
data Dog = Dog String deriving Show
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Map](map.png)
|
2024-02-04 13:16:07 +01:00
|
|
|
|
|
2024-02-04 01:00:25 +01:00
|
|
|
|
```haskell
|
|
|
|
|
class Mappable box where
|
2024-02-04 13:16:07 +01:00
|
|
|
|
map' :: (a -> b) -> box a -> box b
|
2024-02-04 01:00:25 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
```haskell ignore
|
|
|
|
|
class Mappable box where
|
|
|
|
|
map' :: (a -> b) -> box a -> box b
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-04 01:00:25 +01:00
|
|
|
|
```haskell
|
2024-02-04 13:16:07 +01:00
|
|
|
|
instance Mappable Box where
|
|
|
|
|
map' _ Empty = Empty
|
|
|
|
|
map' f (Has a) = Has (f a)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
```
|
|
|
|
|
```haskell
|
2024-02-04 13:16:07 +01:00
|
|
|
|
instance Mappable [] where
|
|
|
|
|
map' _ [] = []
|
|
|
|
|
map' f xs = [f x | x <- xs]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
instance Mappable [] where
|
|
|
|
|
map' _ [] = []
|
|
|
|
|
map' f xs = [f x | x <- xs]
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat list](cat-list.png)
|
2024-02-04 13:16:07 +01:00
|
|
|
|
|
2024-02-05 22:21:39 +01:00
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat list](cat-list.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> a = Has $ Cat "cat"
|
|
|
|
|
λ> :type a
|
|
|
|
|
a :: Box Cat
|
|
|
|
|
λ> :type map' toDog a
|
|
|
|
|
map' toDog a :: Box Dog
|
|
|
|
|
λ> :type map toDog [Cat "a", Cat "b"]
|
|
|
|
|
map toDog [Cat "a", Cat "b"] :: [Dog]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
toDog :: Cat -> Dog
|
|
|
|
|
toDog (Cat name) = Dog name
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
convertAllCats :: Mappable box => box Cat -> box Dog
|
|
|
|
|
convertAllCats cs = map' toDog cs
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
Any "box" can go in 👍
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
convertAllCats :: Mappable box => box Cat -> box Dog
|
|
|
|
|
convertAllCats cs = map' toDog cs
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> convertAllCats [Cat "a", Cat "b"]
|
|
|
|
|
[Dog "a",Dog "b"]
|
|
|
|
|
λ> convertAllCats $ Has $ Cat "a"
|
|
|
|
|
Has (Dog "a")
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
-----
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat merge](cat-merge.png)
|
2024-02-04 13:16:07 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat merge](cat-merge.png)
|
2024-02-04 13:16:07 +01:00
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
merge :: Cat -> Cat -> Dog
|
|
|
|
|
merge (Cat c1) (Cat c2) = Dog $ c1 <> " & " <> c2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
catA = Cat "Meow"
|
|
|
|
|
catB = Cat "Nyaa"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> merge catA catB
|
|
|
|
|
Dog "Meow & Nyaa"
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat merge](merge.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
boxA = Has $ Cat "Meow" :: Box Cat
|
|
|
|
|
boxB = Has $ Cat "Nyaa" :: Box Cat
|
|
|
|
|
empty = Empty :: Box Cat
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat merge](merge-box.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
boxA = Has $ Cat "Meow" :: Box Cat
|
|
|
|
|
boxB = Has $ Cat "Nyaa" :: Box Cat
|
|
|
|
|
empty = Empty :: Box Cat
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat merge](merge-box.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> merge boxA catB
|
|
|
|
|
|
|
|
|
|
<interactive>:7:7: error:
|
|
|
|
|
• Couldn't match expected type ‘Cat’ with actual type ‘Box Cat’
|
|
|
|
|
• In the first argument of ‘merge’, namely ‘boxA’
|
|
|
|
|
In the expression: merge boxA catB
|
|
|
|
|
In an equation for ‘it’: it = merge boxA catB
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
boxA = Has $ Cat "Meow" :: Box Cat
|
|
|
|
|
boxB = Has $ Cat "Nyaa" :: Box Cat
|
|
|
|
|
empty = Empty :: Box Cat
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat merge](merge-prim.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
```haskell
|
|
|
|
|
merge' :: Box Cat -> Box Cat -> Box Dog
|
|
|
|
|
merge' Empty _ = Empty
|
|
|
|
|
merge' _ Empty = Empty
|
|
|
|
|
merge' (Has c1) (Has c2) = Has $ merge c1 c2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
merge' :: Box Cat -> Box Cat -> Box Dog
|
|
|
|
|
merge' Empty _ = Empty
|
|
|
|
|
merge' _ Empty = Empty
|
|
|
|
|
merge' (Has c1) (Has c2) = merge c1 c2
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Cat merge](merge-prim.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> merge' boxA boxB
|
|
|
|
|
Has (Dog "Meow & Nyaa")
|
|
|
|
|
λ> merge' boxA (Has catB)
|
|
|
|
|
Has (Dog "Meow & Nyaa")
|
|
|
|
|
λ> merge' boxA empty
|
|
|
|
|
Empty
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
class Appliable box where
|
|
|
|
|
wrap :: a -> box a
|
|
|
|
|
apply' :: box (a -> b) -> box a -> box b
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Wrap apply](wrap-apply.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
2024-02-04 01:00:25 +01:00
|
|
|
|
class Appliable box where
|
|
|
|
|
wrap :: a -> box a
|
|
|
|
|
apply' :: box (a -> b) -> box a -> box b
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
```haskell
|
|
|
|
|
instance Appliable Box where
|
|
|
|
|
wrap = Has
|
|
|
|
|
apply' Empty _ = Empty
|
|
|
|
|
apply' _ Empty = Empty
|
|
|
|
|
apply' (Has f) (Has a) = Has $ f a
|
|
|
|
|
|
|
|
|
|
instance Appliable [] where
|
|
|
|
|
wrap x = [x]
|
|
|
|
|
apply' [] _ = []
|
|
|
|
|
apply' _ [] = []
|
|
|
|
|
apply' fs xs = [f x | f <- fs, x <- xs]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
instance Appliable Box where
|
|
|
|
|
wrap = Has
|
|
|
|
|
apply' Empty _ = Empty
|
|
|
|
|
apply' _ Empty = Empty
|
|
|
|
|
apply' (Has f) (Has a) = Has $ f a
|
|
|
|
|
|
|
|
|
|
instance Appliable [] where
|
|
|
|
|
wrap x = [x]
|
|
|
|
|
apply' [] _ = []
|
|
|
|
|
apply' _ [] = []
|
|
|
|
|
apply' fs xs = [f x | f <- fs, x <- xs]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> apply' (apply' (wrap merge) boxA) boxB
|
|
|
|
|
Has (Dog "Meow & Nyaa")
|
|
|
|
|
λ> apply' (apply' (wrap merge) boxA) empty
|
|
|
|
|
Empty
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
instance Appliable Box where
|
|
|
|
|
wrap = Has
|
|
|
|
|
apply' Empty _ = Empty
|
|
|
|
|
apply' _ Empty = Empty
|
|
|
|
|
apply' (Has f) (Has a) = Has $ f a
|
|
|
|
|
|
|
|
|
|
instance Appliable [] where
|
|
|
|
|
wrap x = [x]
|
|
|
|
|
apply' [] _ = []
|
|
|
|
|
apply' _ [] = []
|
|
|
|
|
apply' fs xs = [f x | f <- fs, x <- xs]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> apply' (apply' (wrap merge) [Cat "A"]) [Cat "B1", Cat "B2"]
|
|
|
|
|
[Dog "A & B1",Dog "A & B2"]
|
|
|
|
|
λ> apply' (apply' (wrap merge) [Cat "A"]) []
|
|
|
|
|
[]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> apply' (apply' (wrap merge) [Cat "A"]) [Cat "B1", Cat "B2"]
|
|
|
|
|
[Dog "A & B1",Dog "A & B2"]
|
|
|
|
|
λ> apply' (apply' (wrap merge) [Cat "A"]) []
|
|
|
|
|
[]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> wrap merge `apply'` [Cat "A"] `apply'` [Cat "B1", Cat "B2"]
|
|
|
|
|
[Dog "A & B1",Dog "A & B2"]
|
|
|
|
|
λ> wrap merge `apply'` [Cat "A"] `apply'` []
|
|
|
|
|
[]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> wrap merge `apply'` [Cat "A"] `apply'` [Cat "B1", Cat "B2"]
|
|
|
|
|
[Dog "A & B1",Dog "A & B2"]
|
|
|
|
|
λ> wrap merge `apply'` [Cat "A"] `apply'` []
|
|
|
|
|
[]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> wrap merge `apply'` boxA `apply'` boxB
|
|
|
|
|
Has (Dog "Meow & Nyaa")
|
|
|
|
|
λ> wrap merge `apply'` boxA `apply'` empty
|
|
|
|
|
Empty
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Wrap apply](wrap-apply.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 01:00:25 +01:00
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Wrap apply](wrap-apply.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 13:16:07 +01:00
|
|
|
|
```haskell
|
|
|
|
|
merge4 :: Cat -> Cat -> Cat -> Cat -> Dog
|
|
|
|
|
merge4 (Cat a) (Cat b) (Cat c) (Cat d) = Dog $ a <> b <> c <> d
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> wrap merge4 `apply'` boxA `apply'` boxB `apply'` boxA `apply'` boxB
|
|
|
|
|
Has (Dog "MeowNyaaMeowNyaa")
|
|
|
|
|
λ> wrap merge4 `apply'` boxA `apply'` boxB `apply'` empty `apply'` boxB
|
|
|
|
|
Empty
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
```haskell
|
2024-02-05 22:21:39 +01:00
|
|
|
|
killOrSave :: Cat -> Box Cat
|
|
|
|
|
killOrSave cat@(Cat name) = case name of
|
|
|
|
|
"Meow" -> Empty
|
|
|
|
|
_ -> Has cat
|
2024-02-04 13:16:07 +01:00
|
|
|
|
```
|
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
<small>(no animals were harmed in the making of this slideshow)</small>
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
2024-02-05 22:21:39 +01:00
|
|
|
|
killOrSave :: Cat -> Box Cat
|
|
|
|
|
killOrSave cat@(Cat name) = case name of
|
|
|
|
|
"Meow" -> Empty
|
|
|
|
|
_ -> Has cat
|
2024-02-04 15:20:15 +01:00
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Kill](kill.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Kill](kill.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
```haskell ignore
|
2024-02-05 22:21:39 +01:00
|
|
|
|
λ> wrap killOrSave `apply'` Has (Cat "Meow")
|
2024-02-04 15:20:15 +01:00
|
|
|
|
Has Empty
|
2024-02-05 22:21:39 +01:00
|
|
|
|
λ> wrap killOrSave `apply'` Has (Cat "Nyaa")
|
|
|
|
|
Has (Has (Cat "Nyaa"))
|
|
|
|
|
λ> wrap killOrSave `apply'` Empty
|
|
|
|
|
Empty
|
2024-02-04 15:20:15 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-02-04 01:00:25 +01:00
|
|
|
|
```haskell
|
|
|
|
|
class Chainable box where
|
|
|
|
|
chain :: box a -> (a -> box b) -> box b
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
class Chainable box where
|
|
|
|
|
chain :: box a -> (a -> box b) -> box b
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
instance Chainable Box where
|
|
|
|
|
chain Empty _ = Empty
|
|
|
|
|
chain (Has a) f = f a
|
|
|
|
|
|
|
|
|
|
instance Chainable [] where
|
|
|
|
|
chain [] _ = []
|
|
|
|
|
chain xs f = [x' | x <- xs, x' <- f x]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
instance Chainable Box where
|
|
|
|
|
chain Empty _ = Empty
|
|
|
|
|
chain (Has a) f = f a
|
|
|
|
|
|
|
|
|
|
instance Chainable [] where
|
|
|
|
|
chain [] _ = []
|
|
|
|
|
chain xs f = [x' | x <- xs, x' <- f x]
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Save-kill](save-kill.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Save-kill](save-kill.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
2024-02-05 22:21:39 +01:00
|
|
|
|
```haskell
|
|
|
|
|
kill :: Cat -> Box Cat
|
|
|
|
|
kill _ = Empty
|
|
|
|
|
|
|
|
|
|
save :: Cat -> Box Cat
|
|
|
|
|
save = Has
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Save-kill](save-kill.png)
|
2024-02-05 22:21:39 +01:00
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> boxA `chain` save `chain` save `chain` save
|
|
|
|
|
Has (Cat "Meow")
|
|
|
|
|
λ> boxA `chain` save `chain` kill `chain` save
|
|
|
|
|
Empty
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
kill' :: Cat -> [Cat]
|
|
|
|
|
kill' _ = []
|
|
|
|
|
|
|
|
|
|
save' :: Cat -> [Cat]
|
|
|
|
|
save' c = [c]
|
|
|
|
|
|
|
|
|
|
clone :: Cat -> [Cat]
|
|
|
|
|
clone (Cat c) = [Cat $ c <> "L" , Cat $ c <> "R"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
kill' :: Cat -> [Cat]
|
|
|
|
|
kill' _ = []
|
|
|
|
|
|
|
|
|
|
save' :: Cat -> [Cat]
|
|
|
|
|
save' c = [c]
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
clone :: Cat -> [Cat]
|
|
|
|
|
clone (Cat c) = [Cat $ c <> "L" , Cat $ c <> "R"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> [catA] `chain` save' `chain` save' `chain` save'
|
|
|
|
|
[Cat "Meow"]
|
|
|
|
|
λ> [catA] `chain` save' `chain` clone `chain` save'
|
|
|
|
|
[Cat "MeowL",Cat "MeowR"]
|
|
|
|
|
λ> [catA] `chain` more' `chain` clone `chain` save'
|
|
|
|
|
[Cat "MeowLL",Cat "MeowLR",Cat "MeowRL",Cat "MeowRR"]
|
|
|
|
|
λ> [catA] `chain` clone `chain` clone `chain` kill'
|
|
|
|
|
[]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> [catA] `chain` save' `chain` save' `chain` save'
|
|
|
|
|
[Cat "Meow"]
|
|
|
|
|
λ> [catA] `chain` save' `chain` clone `chain` save'
|
|
|
|
|
[Cat "MeowL",Cat "MeowR"]
|
|
|
|
|
λ> [catA] `chain` more' `chain` clone `chain` save'
|
|
|
|
|
[Cat "MeowLL",Cat "MeowLR",Cat "MeowRL",Cat "MeowRR"]
|
|
|
|
|
λ> [catA] `chain` clone `chain` clone `chain` kill'
|
|
|
|
|
[]
|
|
|
|
|
```
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Chain list](chain-list.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Callbacks](callbacks.jpg)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![This was all dream](cave.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
What's a `Mappable`?
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
It's a `Functor`
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![It's a Functor](its-functor.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
It's a `Functor`
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
class Mappable box where
|
|
|
|
|
map' :: (a -> b) -> box a -> box b
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
class Functor f where
|
|
|
|
|
fmap :: (a -> b) -> f a -> f b
|
|
|
|
|
(<$) :: a -> f b -> f a
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
It's a `Functor`
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> map' (+1) []
|
|
|
|
|
[]
|
|
|
|
|
λ> map' (+1) [1, 2, 3]
|
|
|
|
|
[2,3,4]
|
|
|
|
|
λ> map' (*3) [1, 2, 3]
|
|
|
|
|
[3,6,9]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> fmap (+1) []
|
|
|
|
|
[]
|
|
|
|
|
λ> fmap (+1) [1, 2, 3]
|
|
|
|
|
[2,3,4]
|
|
|
|
|
λ> fmap (*3) [1, 2, 3]
|
|
|
|
|
[3,6,9]
|
|
|
|
|
λ> 1 <$ [1, 2, 3]
|
|
|
|
|
[1,1,1]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
It's a `Functor`
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Tardis](tardis.jpg)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
It's a `Functor`
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Tardis inside](tardis-inside.jpg)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
main :: IO ()
|
|
|
|
|
main = print "Hello World!"
|
|
|
|
|
```
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Tardis inside](io.png)
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
What's a `Appliable`?
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
It's an Applicative
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![It's an applicative](its-applicative.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
It's an Applicative
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
class Appliable box where
|
|
|
|
|
wrap :: a -> box a
|
|
|
|
|
apply' :: box (a -> b) -> box a -> box b
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
class (Functor f) => Applicative f where
|
|
|
|
|
pure :: a -> f a
|
|
|
|
|
(<*>) :: f (a -> b) -> f a -> f b
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
It's an Applicative
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> wrap merge `apply'` [catA] `apply'` []
|
|
|
|
|
[]
|
|
|
|
|
λ> wrap merge `apply'` [catA] `apply'` [catB]
|
|
|
|
|
[Dog "Meow & Nyaa"]
|
|
|
|
|
λ> wrap merge `apply'` [catA] `apply'` [catB, Cat "C"]
|
|
|
|
|
[Dog "Meow & Nyaa",Dog "Meow & C"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> pure merge <*> [catA] <*> []
|
|
|
|
|
[]
|
|
|
|
|
λ> pure merge <*> [catA] <*> [catB]
|
|
|
|
|
[Dog "Meow & Nyaa"]
|
|
|
|
|
λ> pure merge <*> [catA] <*> [catB, Cat "C"]
|
|
|
|
|
[Dog "Meow & Nyaa",Dog "Meow & C"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> pure merge <*> [catA] <*> []
|
|
|
|
|
[]
|
|
|
|
|
λ> pure merge <*> [catA] <*> [catB]
|
|
|
|
|
[Dog "Meow & Nyaa"]
|
|
|
|
|
λ> pure merge <*> [catA] <*> [catB, Cat "C"]
|
|
|
|
|
[Dog "Meow & Nyaa",Dog "Meow & C"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> merge <$> [catA] <*> []
|
|
|
|
|
[]
|
|
|
|
|
λ> merge <$> [catA] <*> [catB]
|
|
|
|
|
[Dog "Meow & Nyaa"]
|
|
|
|
|
λ> merge <$> [catA] <*> [catB, Cat "C"]
|
|
|
|
|
[Dog "Meow & Nyaa",Dog "Meow & C"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
merge :: Cat -> Cat -> Dog
|
|
|
|
|
|
|
|
|
|
_ = merge catA catB
|
|
|
|
|
```
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
What's a `Chainable`?
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
It's a monad
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![It's a monad](its-monad.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
It's a monad
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
class Chainable box where
|
|
|
|
|
chain :: box a -> (a -> box b) -> box b
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
class Applicative m => Monad m where
|
|
|
|
|
(>>=) :: m a -> (a -> m b) -> m b
|
|
|
|
|
|
|
|
|
|
(>>) :: m a -> m b -> m b
|
|
|
|
|
m >> k = m >>= \_ -> k
|
|
|
|
|
|
|
|
|
|
return :: a -> m a
|
|
|
|
|
return = pure
|
|
|
|
|
```
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
It's a monad
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
2024-02-04 15:20:15 +01:00
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> [catA] `chain` save' `chain` save' `chain` save'
|
|
|
|
|
[Cat "Meow"]
|
|
|
|
|
λ> [catA] `chain` save' `chain` clone `chain` save'
|
|
|
|
|
[Cat "MeowL",Cat "MeowR"]
|
|
|
|
|
λ> [catA] `chain` save' `chain` clone `chain` kill'
|
|
|
|
|
[]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```haskell ignore
|
|
|
|
|
λ> [catA] >>= save' >>= save' >>= save'
|
|
|
|
|
[Cat "Meow"]
|
|
|
|
|
λ> [catA] >>= save' >>= clone >>= save'
|
|
|
|
|
[Cat "MeowL",Cat "MeowR"]
|
|
|
|
|
λ> [catA] >>= save' >>= clone >>= kill'
|
|
|
|
|
[]
|
|
|
|
|
```
|
2024-02-04 01:00:25 +01:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-04-13 15:26:52 +02:00
|
|
|
|
![Just one more typeclass bro](pepe.png)
|
2024-02-04 15:20:15 +01:00
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
2024-02-04 01:00:25 +01:00
|
|
|
|
## 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
|
|
|
|
|
|