1 | var assert = require('assert');
|
2 | var types = require('./types');
|
3 |
|
4 | var readerTypes = types(function(r1, r2) {
|
5 | return r1.run('x') === r2.run('x');
|
6 | });
|
7 |
|
8 | var transformerTypes = types(function(r1, r2) {
|
9 | return r1.run('x').get() === r2.run('x').get();
|
10 | });
|
11 |
|
12 | var Identity = require('..').Identity;
|
13 | var Reader = require('../src/Reader');
|
14 |
|
15 | var ReaderTIdentity = Reader.T(Identity);
|
16 |
|
17 | function add(a) {
|
18 | return function(b) { return a + b; };
|
19 | }
|
20 |
|
21 | function always(x) {
|
22 | return function() { return x; };
|
23 | }
|
24 |
|
25 | function mult(a) {
|
26 | return function(b) { return a * b; };
|
27 | }
|
28 |
|
29 | function identity(x) { return x; }
|
30 |
|
31 | describe('Reader properties', function() {
|
32 |
|
33 | var f1 = function(x) { return x + '1 '; };
|
34 | var f2 = function(x) { return x + '2 '; };
|
35 | var f3 = function(x) { return x + '3 '; };
|
36 | var r1 = Reader(f1);
|
37 | var r2 = Reader(f2);
|
38 |
|
39 | it('is a Functor', function() {
|
40 | var fTest = readerTypes.functor;
|
41 | assert.ok(fTest.iface(r1));
|
42 | assert.ok(fTest.id(r1));
|
43 | assert.ok(fTest.compose(r1, f2, f3));
|
44 | });
|
45 |
|
46 | it('is an Apply', function() {
|
47 | var aTest = readerTypes.apply;
|
48 | var a = Reader(function() { return add(1); });
|
49 | var b = Reader(function() { return always(2); });
|
50 | var c = Reader(always(4));
|
51 |
|
52 | assert.equal(true, aTest.iface(r1));
|
53 | assert.equal(true, aTest.compose(a, b, c));
|
54 | });
|
55 |
|
56 | it('is an Applicative', function() {
|
57 | var aTest = readerTypes.applicative;
|
58 |
|
59 | assert.equal(true, aTest.iface(r1));
|
60 | assert.equal(true, aTest.id(Reader, r2));
|
61 | assert.equal(true, aTest.homomorphic(r1, add(3), 46));
|
62 | assert.equal(true, aTest.interchange(
|
63 | Reader(function() { return mult(20); }),
|
64 | Reader(function() { return mult(0.5); }),
|
65 | 73
|
66 | ));
|
67 | });
|
68 |
|
69 | it('is a Chain', function() {
|
70 | var cTest = readerTypes.chain;
|
71 | var c = Reader(function() {
|
72 | return Reader(function() {
|
73 | return Reader(function() {
|
74 | return 3;
|
75 | });
|
76 | });
|
77 | });
|
78 | assert.equal(true, cTest.iface(r1));
|
79 | assert.equal(true, cTest.associative(c, identity, identity));
|
80 | });
|
81 |
|
82 | it('is a Monad', function() {
|
83 | var mTest = readerTypes.monad;
|
84 | assert.equal(true, mTest.iface(r1));
|
85 | });
|
86 |
|
87 | describe('.ask', function() {
|
88 | it('provides access to the environment', function() {
|
89 | var r = Reader.ask.map(add(100));
|
90 | assert.equal(101, r.run(1));
|
91 | });
|
92 | });
|
93 |
|
94 | describe('#toString', function() {
|
95 |
|
96 | it('returns the string representation of a Reader', function() {
|
97 | assert.strictEqual(Reader(function(x) { void x; }).toString(),
|
98 | 'Reader(function (x) { void x; })');
|
99 | });
|
100 |
|
101 | });
|
102 |
|
103 | });
|
104 |
|
105 | describe('Reader examples', function() {
|
106 | it('should write name of options object', function() {
|
107 |
|
108 | var options = {name: 'header'};
|
109 | var Printer = {};
|
110 | Printer.write = function(x) {
|
111 | return '/** ' + x + ' */';
|
112 | };
|
113 |
|
114 | function getOptionsName(opts) {
|
115 | return Reader(function(printer) {
|
116 | return printer.write(opts.name);
|
117 | });
|
118 | }
|
119 |
|
120 | var nameReader = getOptionsName(options);
|
121 |
|
122 | assert.equal(Reader.run(nameReader, Printer), '/** header */');
|
123 | });
|
124 | });
|
125 |
|
126 | describe('Reader.T', function() {
|
127 | var r1 = ReaderTIdentity(function(x) {
|
128 | return Identity(x + '1 ');
|
129 | });
|
130 | var r2 = ReaderTIdentity(function(x) {
|
131 | return Identity(x + '2 ');
|
132 | });
|
133 |
|
134 | it('is a Functor', function() {
|
135 | var fTest = transformerTypes.functor;
|
136 | assert(fTest.iface(r1));
|
137 | assert(fTest.id(r1));
|
138 | assert(fTest.compose(r1,
|
139 | function(x) { return x + 'a'; },
|
140 | function(x) { return x + 'b'; }
|
141 | ));
|
142 | });
|
143 |
|
144 | it('is an Apply', function() {
|
145 | var aTest = transformerTypes.apply;
|
146 | var a = ReaderTIdentity(function() { return Identity(add(1)); });
|
147 | var b = ReaderTIdentity(function() { return Identity(always(2)); });
|
148 | var c = ReaderTIdentity(always(Identity(4)));
|
149 |
|
150 | assert(aTest.iface(r1));
|
151 | assert(aTest.compose(a, b, c));
|
152 | });
|
153 |
|
154 | it('is an Applicative', function() {
|
155 | var aTest = transformerTypes.applicative;
|
156 |
|
157 | assert(aTest.iface(r1));
|
158 | assert(aTest.id(ReaderTIdentity, r2));
|
159 | assert(aTest.homomorphic(r1, add(3), 46));
|
160 | assert(aTest.interchange(
|
161 | ReaderTIdentity(function() { return Identity(mult(20)); }),
|
162 | ReaderTIdentity(function() { return Identity(mult(0.5)); }),
|
163 | 73
|
164 | ));
|
165 | });
|
166 |
|
167 | it('is a Chain', function() {
|
168 | var cTest = transformerTypes.chain;
|
169 | var c = ReaderTIdentity(function() {
|
170 | return Identity(ReaderTIdentity(function() {
|
171 | return Identity(ReaderTIdentity(function() {
|
172 | return Identity(3);
|
173 | }));
|
174 | }));
|
175 | });
|
176 | assert(cTest.iface(r1));
|
177 | assert(cTest.associative(c, identity, identity));
|
178 | });
|
179 |
|
180 | it('is a Monad', function() {
|
181 | var mTest = transformerTypes.monad;
|
182 | assert(mTest.iface(r1));
|
183 | });
|
184 |
|
185 | it('is a Transformer', function() {
|
186 | var mtTest = transformerTypes.transformer;
|
187 | assert(mtTest.iface(Reader.T));
|
188 | assert(mtTest.id(Reader.T));
|
189 | assert(mtTest.associative(Reader.T));
|
190 | });
|
191 | });
|
192 |
|
193 | describe('Reader.T examples', function() {
|
194 | it('should provide its environment to a lifted monad', function() {
|
195 | var readerTimes10 = ReaderTIdentity.ask.chain(function(env) {
|
196 | return ReaderTIdentity.lift(Identity(env * 10));
|
197 | });
|
198 | assert.strictEqual(readerTimes10.run(3).get(), 30);
|
199 | });
|
200 | });
|