-
Notifications
You must be signed in to change notification settings - Fork 9
/
index2.js
67 lines (52 loc) · 1.69 KB
/
index2.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
const request = require('request');
const Task = require('data.task');
const Either = require('data.either');
const { List } = require('immutable-ext');
const Sum = x => ({
x,
concat: ({ x: y }) => Sum(x + y),
inspect: () => `Sum(${x})`
});
Sum.empty = () => Sum(0);
const Pair = (x, y) => ({
x,
y,
bimap: (f, g) => Pair(f(x), g(y)),
toList: () => [x, y],
concat: ({ x: x1, y: y1 }) => Pair(x.concat(x1), y.concat(y1)),
inspect: () => `Pair(${x}, ${y})`
});
const httpGet = url =>
new Task((rej, res) =>
request(url, (error, response, body) => error ? rej(error) : res(body)));
const getJSON = url => httpGet(url).map(parse).chain(eitherToTask);
const first = xs => Either.fromNullable(xs[0]);
const eitherToTask = e => e.fold(Task.rejected, Task.of);
const parse = Either.try(JSON.parse);
const findArtist = name =>
getJSON(`https://api.spotify.com/v1/search?q=${name}&type=artist`)
.map(result => result.artists.items)
.map(first)
.chain(eitherToTask);
const relatedArtists = id =>
getJSON(`https://api.spotify.com/v1/artists/${id}/related-artists`).map(
result => result.artists
);
const Intersection = xs => ({
xs,
concat: ({ xs: ys }) => Intersection(xs.filter(x => ys.some(y => x === y)))
});
const related = name => findArtist(name)
.map(artist => artist.id)
.chain(relatedArtists)
.map(artists => artists.map(artist => artist.name));
const artistIntersection = rels => rels
.foldMap(x => Pair(Intersection(x), Sum(x.length)))
.bimap(x => x.xs, y => y.x)
.toList();
const main = names =>
List(names).traverse(Task.of, related).map(artistIntersection);
Task
.of(['oasis', 'blur', 'radiohead'])
.chain(main)
.fork(console.error, console.log);