forked from gcanti/fp-ts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path11.ts
89 lines (71 loc) · 2.16 KB
/
11.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//
// Code for http://www.tomharding.me/2017/05/01/fantas-eel-and-specification-11/
//
import { toString } from '../src/function'
declare module '../src/HKT' {
interface URI2HKT<A> {
BTree: BTree<A>
}
}
export const URI = 'BTree'
export type URI = typeof URI
export class Leaf<A> {
static value = new Leaf<never>()
readonly _tag: 'Leaf' = 'Leaf'
readonly '-A': A
readonly '-URI' = URI
private constructor() {}
inspect(): string {
return this.toString()
}
toString(): string {
return `leaf`
}
}
export class Node<A> {
readonly _tag: 'Node' = 'Node'
readonly '-A': A
readonly '-URI' = URI
constructor(readonly left: BTree<A>, readonly value: A, readonly right: BTree<A>) {}
inspect(): string {
return this.toString()
}
toString(): string {
return `node(${toString(this.left)}, ${toString(this.value)}, ${toString(this.right)})`
}
}
export type BTree<A> = Leaf<A> | Node<A>
export const leaf = Leaf.value
export const node = <A>(left: BTree<A>, value: A, right: BTree<A>): BTree<A> => new Node(left, value, right)
export const fold = <A, R>(leaf: () => R, node: (left: BTree<A>, value: A, right: BTree<A>) => R, fa: BTree<A>): R => {
switch (fa._tag) {
case 'Leaf':
return leaf()
case 'Node':
return node(fa.left, fa.value, fa.right)
}
}
const myTree = node(node(leaf, 1, new Node<number>(leaf, 2, leaf)), 3, node(node<number>(leaf, 4, leaf), 5, leaf))
console.log(myTree)
// => node(node(leaf, 1, node(leaf, 2, leaf)), 3, node(node(leaf, 4, leaf), 5, leaf))
export const reduce = <A, B>(fa: BTree<A>, b: B, f: (acc: B, a: A) => B): B =>
fold(
() => b,
(l, v, r) => {
// Reduce the tree on the left...
const left = reduce(l, b, f)
// Plus the middle element...
const leftAndMiddle = f(left, v)
// And then the right tree...
return reduce(r, leftAndMiddle, f)
},
fa
)
console.log(reduce(myTree, 0, (acc, a) => acc + a)) // => 15
import { Foldable1, foldMap } from '../src/Foldable'
export const btree: Foldable1<URI> = {
URI,
reduce
}
import { monoidSum } from '../src/Monoid'
console.log(foldMap(btree, monoidSum)(myTree, (a: number) => a)) // => 15