UNPKG

5.2 kBJavaScriptView Raw
1var R = require('ramda');
2var assert = require('assert');
3var types = require('./types');
4var jsv = require('jsverify');
5
6var Tuple = require('..').Tuple;
7var constructor = Tuple('', '').constructor;
8
9var TupleGen = R.curry(function(a, b, n) {
10 return Tuple(a.generator(n), b.generator(n));
11});
12
13var TupleShow = R.curry(function(a, m) {
14 return 'Tuple(' + a.show(m[0]) + ', ' + a.show(m[1]) + ')';
15});
16
17var TupleShrink = R.curry(function(a, m) {
18 return [Tuple(a.shrink(m[0]), a.shrink(m[1]))];
19});
20
21var TupleArb = function(a, b) {
22 return {
23 generator: jsv.generator.bless(TupleGen(a, b)),
24 show: TupleShow(a),
25 shrink: jsv.shrink.bless(TupleShrink(a))
26 };
27};
28
29var stringArb = jsv.generator.bless({
30 generator: function() {
31 switch (jsv.random(0, 2)) {
32 case 0: return 'foo';
33 case 1: return 'bar';
34 case 2: return 'quux';
35 }
36 },
37 show: function(a) { return a; },
38 shrink: jsv.shrink.bless(function(m) { return [m.slice(1)]; })
39});
40
41function mult(a) {
42 return function(b) { return a * b; };
43}
44
45function add(a) {
46 return function(b) { return a + b; };
47}
48
49
50describe('Tuple', function() {
51 var m = TupleArb(stringArb, jsv.nat);
52
53 it('has an arbitrary', function() {
54 var arb = jsv.forall(m, function(m) {
55 return m instanceof constructor;
56 });
57 jsv.assert(arb);
58 });
59
60 it('is a Semigroup', function() {
61 var t = TupleArb(stringArb, stringArb);
62 var t1 = TupleArb(stringArb, stringArb);
63 var t2 = TupleArb(stringArb, stringArb);
64 var sTest = types.semigroup;
65
66 jsv.assert(jsv.forall(t, sTest.iface));
67 jsv.assert(jsv.forall(t, t1, t2, sTest.associative));
68 });
69
70 it('is a Functor', function() {
71 var fTest = types.functor;
72
73 jsv.assert(jsv.forall(m, fTest.iface));
74 jsv.assert(jsv.forall(m, fTest.id));
75 jsv.assert(jsv.forall(m, 'nat -> nat', 'nat -> nat', fTest.compose));
76 });
77
78 it('is an Apply', function() {
79 var aTest = types.apply;
80 var appA = Tuple('', mult(10));
81 var appU = Tuple('', add(7));
82 var appV = Tuple('', 10);
83
84 jsv.assert(jsv.forall(m, aTest.iface));
85 assert.equal(true, aTest.compose(appA, appU, appV));
86 });
87
88 it('is an Applicative', function() {
89 var aTest = types.applicative;
90 var app1 = Tuple('', 101);
91 var app2 = Tuple('', -123);
92 var appF = Tuple('', mult(3));
93
94 assert.equal(true, aTest.iface(app1));
95 assert.equal(true, aTest.id(app1, app2));
96 assert.equal(true, aTest.homomorphic(app1, add(3), 46));
97 assert.equal(true, aTest.interchange(app2, appF, 17));
98 });
99});
100
101describe('Tuple usage', function() {
102
103 describe('creation', function() {
104 it('should be curried', function() {
105 var tpl = Tuple('dr')(true);
106 assert.equal('dr', tpl[0]);
107 assert.equal(true, tpl[1]);
108 });
109
110 it('should lift the value into the tuple as both positions', function() {
111 var tpl = Tuple.of('pillow pets');
112 assert.equal('pillow pets', tpl[0]);
113 assert.equal('pillow pets', tpl[1]);
114 });
115
116 it('should maintain the current fst if it already has one', function() {
117 var tpl = Tuple.of(100).of('buckaroonies');
118 assert.equal(100, tpl[0]);
119 assert.equal('buckaroonies', tpl[1]);
120 });
121 });
122
123 describe('element access', function() {
124 var tuple = Tuple('nacho', 'cheese');
125
126 it('should work with indexes', function() {
127 assert.equal('nacho', tuple[0]);
128 assert.equal('cheese', tuple[1]);
129 });
130
131 it('should return the value in the first position', function() {
132 assert.equal('nacho', Tuple.fst(tuple));
133 assert.equal('cheese', Tuple.snd(tuple));
134 });
135
136 it('should work with head', function() {
137 assert.equal('nacho', R.head(tuple));
138 });
139
140 it('should work with nth', function() {
141 assert.equal('cheese', R.nth(1, tuple));
142 });
143
144 it('should work with tail', function() {
145 assert.equal('cheese', R.tail(tuple));
146 });
147
148 it('should work with take', function() {
149 assert.equal('nacho', R.take(1, tuple)[0]);
150 }
151 );
152 it('should work with drop', function() {
153 assert.equal('cheese', R.drop(1, tuple)[0]);
154 });
155
156 it('will tell us the length', function() {
157 assert.equal(2, tuple.length);
158 });
159 });
160
161 describe('interface sanity check', function() {
162 var tuple = Tuple('mixed', 'nuts');
163
164 it('only maps the snd', function() {
165 var t = tuple.map(add('coco'));
166 assert.equal('mixed', t[0]);
167 assert.equal('coconuts', t[1]);
168 });
169
170 it('will combine two tuples', function() {
171 var t = tuple.concat(Tuple(' chocolate', ' bars'));
172 assert.equal('mixed chocolate', t[0]);
173 assert.equal('nuts bars', t[1]);
174 });
175
176 it('will apply and concat', function() {
177 var t = Tuple('Re', 'dough').map(add).ap(tuple);
178 assert.equal('Remixed', t[0]);
179 assert.equal('doughnuts', t[1]);
180 });
181 });
182
183 describe('#toString', function() {
184
185 it('returns the string representation of a Tuple', function() {
186 assert.strictEqual(Tuple('abc', [1, 2, 3]).toString(),
187 'Tuple("abc", [1, 2, 3])');
188 assert.strictEqual(Tuple('abc', Tuple(1, 2)).toString(),
189 'Tuple("abc", Tuple(1, 2))');
190 });
191
192 });
193
194});