@fpjs/overture
Version:
A Javascript prelude
57 lines (47 loc) • 2.11 kB
JavaScript
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import {id, compose} from "@fpjs/overture/base";
import {map} from "@fpjs/overture/algebras/functor";
import {Identity, runIdentity} from "@fpjs/overture/data/identity";
import {Const, getConst} from "@fpjs/overture/data/const";
///:: type Lens s t a b = Functor f => (a -> f b) -> s -> f t
///:: Lens s t a b -> s -> t
export const view = (l) => (s) => getConst (l (Const) (s));
///:: Lens s t a b -> b -> s -> t
export const set = (l) => (b) => (s) => runIdentity (l (() => Identity (b)) (s));
///:: Lens s t a b -> (a -> b) -> s -> t
export const over = (l) => (f) => (s) => runIdentity (l ((x) => Identity (f (x))) (s));
/**
* Compose pairs of Lens and value to a single setter, such that:
*
* setAll ([l, b]) ≡ set (l) (b)
*/
//:: [(Lens s t a b, b)] -> (s) -> t
export const setAll = (...pairs) =>
pairs.reduce ((acc, [l, b]) => compose (set (l) (b)) (acc), id);
///:: Lens s t a b
export const identity = (f) => (x) => f (x);
/** Accessors for tuples. */
export const Tuple = {
_1: (f) => ([a,...rest]) => map ((a_) => [a_,...rest]) (f (a)),
_2: (f) => ([a,b,...rest]) => map ((b_) => [a,b_,...rest]) (f (b)),
_3: (f) => ([a,b,c,...rest]) => map ((c_) => [a,b,c_,...rest]) (f (c)),
_4: (f) => ([a,b,c,d,...rest]) => map ((d_) => [a,b,c,d_,...rest]) (f (d)),
_5: (f) => ([a,b,c,d,e,...rest]) => map ((e_) => [a,b,c,d,e_,...rest]) (f (e)),
};
/** Accessors for records. */
const makeLensFor = (fieldName) => (f) => (s) =>
map ((x) => ({...s, [fieldName]: x})) (f (s[fieldName]));
const RecordFields = (l) => new Proxy(
l,
{
get: (target, prop) => RecordFields (compose (target) (makeLensFor (prop))),
}
);
export const Record = RecordFields(identity);
/** Accessors for indexed values (e.g. Array). */
export const Indexed = {
ix: (n) => (f) => (xs) =>
map ((y) => [...xs.slice(0, n), y, ...xs.slice(n+1)]) (f (xs[n])),
};