data.types.js
1 const Reducer = run => ({ 2 run, 3 concat: other => Reducer((acc, x) => other.run(run(acc, x), x)), 4 contramap: f => Reducer((acc, x) => run(acc, f(x))), 5 map: f => Reducer((acc, x) => f(run(acc, x))) 6 }); 7 8 const Id = x => ({ 9 map: f => Id(f(x)), 10 chain: f => f(x), 11 extract: () => x, 12 concat: o => Id(x.concat(o.extract())) 13 }); 14 Id.of = x => Id(x); 15 16 const IdT = M => { 17 const Id = mx => ({ 18 map: f => Id(mx.map(f)), 19 chain: f => Id(mx.chain(x => f(x).extract())), 20 extract: () => mx 21 }); 22 Id.of = x => Id(M.of(x)); 23 Id.lift = mx => Id(mx); 24 return Id; 25 }; 26 27 const IO = run => ({ 28 run, 29 map: f => IO(() => f(run())), 30 chain: f => IO(() => f(run()).run()), 31 concat: other => IO(() => run().concat(other.run())) 32 }); 33 IO.of = x => IO(() => x); 34 35 const Fn = g => ({ 36 map: f => Fn(x => f(g(x))), 37 chain: f => Fn(x => f(g(x)).run(x)), 38 concat: other => Fn(x => g(x).concat(other.run(x))), 39 run: g 40 }); 41 Fn.ask = Fn(x => x); 42 Fn.of = x => Fn(() => x); 43 44 const FnT = M => { 45 const Fn = g => ({ 46 map: f => Fn(x => g(x).map(f)), 47 chain: f => Fn(x => g(x).chain(y => f(y).run(x))), 48 concat: other => Fn(x => g(x).concat(other.run(x))), 49 run: g 50 }); 51 Fn.ask = Fn(x => M.of(x)); 52 Fn.of = x => Fn(() => M.of(x)); 53 Fn.lift = x => Fn(() => x); 54 return Fn; 55 }; 56 57 const Either = (() => { 58 const Right = x => ({ 59 isLeft: false, 60 chain: f => f(x), 61 ap: other => other.map(x), 62 alt: other => Right(x), 63 extend: f => f(Right(x)), 64 concat: other => 65 other.fold( 66 x => other, 67 y => Right(x.concat(y)) 68 ), 69 traverse: (of, f) => f(x).map(Right), 70 map: f => Right(f(x)), 71 fold: (_, g) => g(x), 72 toString: () => `Right(${x})` 73 }); 74 75 const Left = x => ({ 76 isLeft: true, 77 chain: _ => Left(x), 78 ap: _ => Left(x), 79 extend: _ => Left(x), 80 alt: other => other, 81 concat: _ => Left(x), 82 traverse: (of, _) => of(Left(x)), 83 map: _ => Left(x), 84 fold: (f, _) => f(x), 85 toString: () => `Left(${x})` 86 }); 87 88 const of = Right; 89 const tryCatch = f => { 90 try { 91 return Right(f()); 92 } catch (e) { 93 return Left(e); 94 } 95 }; 96 97 const fromUndefined = x => (x === undefined ? Right(x) : Left(x)); 98 99 const fromNullable = x => (x != null ? Right(x) : Left(x)); 100 101 return { Right, Left, of, tryCatch, fromNullable, fromUndefined }; 102 })(); 103 104 const EitherT = M => { 105 const Right = mx => ({ 106 isLeft: false, 107 extract: () => mx, 108 chain: f => Right(mx.chain(x => f(x).extract())), 109 map: f => Right(mx.map(f)), 110 fold: (_, g) => g(mx) 111 }); 112 113 const Left = mx => ({ 114 isLeft: true, 115 extract: () => mx, 116 chain: _ => Left(mx), 117 map: _ => Left(mx), 118 fold: (h, _) => h(mx) 119 }); 120 121 const of = x => Right(M.of(x)); 122 const tryCatch = f => { 123 try { 124 return Right(M.of(f())); 125 } catch (e) { 126 return Left(e); 127 } 128 }; 129 130 const lift = Right; 131 132 return { of, tryCatch, lift, Right, Left }; 133 }; 134 135 const Task = fork => ({ 136 fork, 137 ap: other => 138 Task((rej, res) => fork(rej, f => other.fork(rej, x => res(f(x))))), 139 map: f => Task((rej, res) => fork(rej, x => res(f(x)))), 140 chain: f => Task((rej, res) => fork(rej, x => f(x).fork(rej, res))), 141 concat: other => 142 Task((rej, res) => fork(rej, x => other.fork(rej, y => res(x.concat(y))))), 143 fold: (f, g) => 144 Task((rej, res) => 145 fork( 146 x => f(x).fork(rej, res), 147 x => g(x).fork(rej, res) 148 ) 149 ) 150 }); 151 Task.of = x => Task((rej, res) => res(x)); 152 Task.rejected = x => Task((rej, res) => rej(x)); 153 Task.fromPromised = 154 fn => 155 (...args) => 156 Task((rej, res) => 157 fn(...args) 158 .then(res) 159 .catch(rej) 160 ); 161 162 const TaskT = M => { 163 const Task = fork => ({ 164 fork, 165 map: f => Task((rej, res) => fork(rej, mx => res(mx.map(f)))), 166 chain: f => 167 Task((rej, res) => fork(rej, mx => mx.chain(x => f(x).fork(rej, res)))) 168 }); 169 Task.lift = x => Task((rej, res) => res(x)); 170 Task.of = x => Task((rej, res) => res(M.of(x))); 171 Task.rejected = x => Task((rej, res) => rej(x)); 172 173 return Task; 174 }; 175 176 const State = run => ({ 177 run, 178 chain: f => 179 State(x => { 180 const [y, s] = run(x); 181 return f(y).run(s); 182 }), 183 map: f => 184 State(x => { 185 const [y, s] = run(x); 186 return [f(y), s]; 187 }), 188 concat: other => 189 State(x => { 190 const [y, s] = run(x); 191 const [y1, _s1] = other.run(x); 192 return [y.concat(y1), s]; 193 }) 194 }); 195 196 State.of = x => State(s => [x, s]); 197 State.get = State(x => [x, x]); 198 State.modify = f => State(s => [null, f(s)]); 199 State.put = x => State(s => [null, x]); 200 201 const StateT = M => { 202 const State = run => ({ 203 run, 204 chain: f => State(x => run(x).chain(([y, s]) => f(y).run(s))), 205 map: f => State(x => run(x).map(([y, s]) => [f(y), s])), 206 concat: other => 207 State(x => 208 run(x).chain(([y, s]) => 209 other.run(x).map(([y1, s1]) => [y.concat(y1), s]) 210 ) 211 ) 212 }); 213 214 State.lift = m => State(s => m.map(x => [x, s])); 215 State.of = x => State(s => M.of([x, s])); 216 State.get = State(x => M.of([x, x])); 217 State.modify = f => State(s => M.of([null, f(s)])); 218 State.put = x => State(s => M.of([null, x])); 219 220 return State; 221 }; 222 223 export { 224 Id, 225 IdT, 226 Task, 227 TaskT, 228 State, 229 StateT, 230 Fn, 231 FnT, 232 Either, 233 EitherT, 234 IO, 235 Reducer 236 };