-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample.js
86 lines (55 loc) · 2.23 KB
/
example.js
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
const { adt: {Type},
monoid: {Fn},
lambda: {curry, pipe},
operation: {map, prop, foldMap} } = require('futils');
/********** DATA TYPES **********/
// data Matrix = Matrix (Array String)
const Matrix = Type('Matrix', ['value']);
Matrix.fn.map = function (f) {
return Matrix(this.value.map(f));
}
Matrix.fn.reduce = function (f, a) {
return this.value.reduce(f, a);
}
// data Char = Char String
const Char = Type('Char', ['value']);
Char.fn.map = function (f) {
return Char(String.fromCharCode(f(this.value.charCodeAt(0))));
}
/********** PARSER **********/
// Parser :: Object (String : String -> Fn (Number -> Number))
const Parser = {
'=': val => Fn(() => Number(val.replace('=', ''))),
'+': val => Fn(n => n + Number(val.replace('+', ''))),
'-': val => Fn(n => n - Number(val.replace('-', ''))),
'*': val => Fn(n => n * Number(val.replace('*', ''))),
'/': val => Fn(n => n / Number(val.replace('/', '')))
}
/********** FUNCTIONS **********/
// split :: String|Regex -> String -> Array String
const split = curry((mark, str) => str.split(mark));
// join :: String -> Array String -> String
const join = curry((mark, xs) => xs.join(mark));
// toChars :: String -> Array (Array (Array String))
const toChars = pipe(
split(/\r|\n|\r\n/g),
map(split(/\s+/g)),
map(map(split(''))));
// fromChars :: Array (Array (Array String)) -> String
const fromChars = pipe(
map(map(join(''))),
map(join(' ')),
join('\n'));
// interpret :: (Matrix, Parser) -> (Number -> Number)
const interpret = (m, p) => foldMap(x => p[x[0]](x), m).value;
// transform :: (Matrix, Parser) -> (String -> String)
const transform = (m, p) => pipe(Char, map(interpret(m, p)), prop('value'));
// convert :: Matrix -> Parser -> (String -> String)
const convert = curry((m, p) => pipe(toChars, map(map(map(transform(m, p)))), fromChars));
/* ========= TEST ========= */
const encoderMatrix = Matrix(['*2', '+2', '/2']);
const decoderMatrix = Matrix(['*2', '-2', '/2']);
const encoder = convert(encoderMatrix, Parser);
const decoder = convert(decoderMatrix, Parser);
console.log(`Encoded 'Hello world': ${encoder('Hello world')}`);
console.log(`Homomorphism? ${encoder(decoder('Hello world')) === 'Hello world'}`);