UNPKG

focused

Version:

Lens/Optics library for JavaScript

79 lines (68 loc) 2.35 kB
import { id, konst, curry2, curry3 } from "./utils"; import { ConstAny, ConstFirst, ConstList, ConstVoid, Identity, List } from "./typeClasses"; import { compose2Isos } from "./iso"; import { compose2Prisms } from "./prism"; /* type Settable<S,T,A,B> = (Identity, A => Identity<B>, S) => Identity<T> type Getting<R,S,A> = (Const<R>, A => Const<R,A>, S) => Const<R,S> type Getter<S,A> = <R>Getting<R,S,A> -- ie should work for any R */ // view : Getting<A,S,A> => S => A export const view = curry2(function _view(aGetter, s) { return aGetter(ConstVoid, id, s); }); function _over(aSettable, f, s) { return aSettable(Identity, f, s); } // over : Settable<S,T,A,B> => (A => B) => S => T export const over = curry3(_over); // set : Settable<S,T,A,B> => B => S => T export const set = curry3(function _set(aSettable, v, s) { return _over(aSettable, konst(v), s); }); // toList : Getting<[A], S,A> => S => [A] export const toList = curry2(function toList(aGetting, s) { return aGetting(ConstList, List.pure, s); }); // preview : Getting<A | null, S,A> => S => (A | null) export const preview = curry2(function _preview(aGetting, s) { return aGetting(ConstFirst, id, s); }); // has : (Getting<Boolean, S,A>, S) => Boolean export const has = curry2(function _has(aGetting, s) { return aGetting(ConstAny, konst(true), s); }); /** * Compose 2 optics, Abstarcting the constraints, the type can be seen as * * compose2 : (Optic<S,T,A,B>, Optic<A,B,X,Y>) => Optic<S,T,A,B> * * However, we need also to combine 2 Isos into an Iso and idem for Prisms * In Haskell this is acheived using type classes & Profunctors * * Here we're just inspecting types at runtime, it's ugly and less flexible but * works for our limited cases. Most notably, I don't want to introduce Profunctors * for performance reasons. */ export function compose2(parent, child) { // ad-hoc polymporphism FTW if (parent.__IS_ISO && child.__IS_ISO) { return compose2Isos(parent, child); } if (parent.__IS_PRISM && child.__IS_PRISM) { return compose2Prisms(parent, child); } return function composedOptics(F, f, s) { return parent(F, a => child(F, f, a), s); }; } export function compose(...ls) { return ls.reduce(compose2); }