forked from gcanti/fp-ts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path3.ts
82 lines (68 loc) · 2.24 KB
/
3.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
//
// Code for http://www.tomharding.me/2017/03/09/fantas-eel-and-specification-3/
//
import { Setoid } from '../src/Setoid'
export class Coord {
/** A coordinate in 3D space */
constructor(readonly x: number, readonly y: number, readonly z: number) {}
translate(deltaX: number, deltaY: number, deltaZ: number) {
return new Coord(this.x + deltaX, this.y + deltaY, this.x + deltaZ)
}
equals(that: Coord): boolean {
return this.x === that.x && this.y === that.y && this.z === that.z
}
}
export class Line {
/** A line between two coordinates */
constructor(readonly from: Coord, readonly to: Coord) {}
equals(that: Line): boolean {
return this.from.equals(that.from) && this.to.equals(that.to)
}
}
export type List<A> = Nil<A> | Cons<A>
export class Nil<A> {
static value: List<never> = new Nil()
private constructor() {}
fold<R>(whenNil: () => R, whenCons: (head: A, tail: List<A>) => R): R {
return whenNil()
}
map<B>(f: (a: A) => B): List<B> {
return Nil.value
}
toString() {
return 'Nil.value'
}
equals(S: Setoid<A>, that: List<A>): boolean {
return isNil(this)
}
}
export class Cons<A> {
constructor(readonly head: A, readonly tail: List<A>) {}
fold<R>(whenNil: () => R, whenCons: (head: A, tail: List<A>) => R): R {
return whenCons(this.head, this.tail)
}
map<B>(f: (a: A) => B): List<B> {
return new Cons(f(this.head), this.tail.map(f))
}
toString() {
return `new Cons(${this.head}, ${this.tail})`
}
equals(S: Setoid<A>, that: List<A>): boolean {
return that.fold(() => false, (head, tail) => S.equals(this.head, head) && this.tail.equals(S, tail))
}
}
export const isNil = <A>(xs: List<A>): xs is Nil<A> => xs === Nil.value
export const equals = <A>(S: Setoid<A>) => (xs: List<A>) => (ys: List<A>): boolean => xs.equals(S, ys)
//
// derivations
//
export const notEquals = <A>(S: Setoid<A>) => (x: A) => (y: A): boolean => !S.equals(x, y)
//
// nub implementation
//
import { findIndex } from '../src/Array'
import { setoidNumber } from '../src/Setoid'
const nub = <A>(S: Setoid<A>) => (xs: Array<A>): Array<A> =>
xs.filter((x, i) => findIndex(xs, (a: A) => S.equals(x, a)).exists(j => i === j))
console.log(nub(setoidNumber)([1, 2, 3, 4, 2, 3]))
// => [ 1, 2, 3, 4 ]