/ contract / data.types.js
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  };