Skip to content

Instantly share code, notes, and snippets.

@outbreak
Last active July 31, 2018 11:28
Show Gist options
  • Save outbreak/ce4dff7d1350328100c00eca23e5891a to your computer and use it in GitHub Desktop.
Save outbreak/ce4dff7d1350328100c00eca23e5891a to your computer and use it in GitHub Desktop.
Functional Lenses (Van Laarhoven)
// Combinators
const K = a => b => a
const I = a => a
// Operators
const eq = a => b => a === b
// Types
const typeOf = a => typeof a
const isArray = a => Array.isArray(a)
// Lists
const reverse = xs => xs.slice().reverse()
const reduce = f => a => xs => xs.reduce(f, a)
// Functions
const compose = (...fns) => x => reduce((acc, fn) => fn(acc))(x)(reverse(fns))
// Objects
const assign = Object.assign
const prop = key => x => x[key]
const assoc = key => value => x => assign(isArray(x) ? [] : {}, x, {[key]: value})
// Functors
const Identity = value => ({ join: K(value), map: fn => Identity(fn(value))})
const Constant = value => ({ join: K(value), map: () => Constant(value)})
// Lenses
const Lens = (get, set) => fn => x => fn(get(x || {})).map((value) => set(value)(x))
const Prop = name => Lens(prop(name), assoc(name))
const Get = lens => x => lens(Constant)(x).join()
const Over = lens => f => x => lens(compose(Identity, f))(x).join()
const Set = lens => v => x => Over(lens)(K(v))(x)
// Example
const o = {a: {b: {c: 0}}}
const a = Prop('a')
const b = Prop('b')
const c = Prop('c')
const abc = compose(a, b, c)
console.log(Get(abc)(o))
console.log(Get(abc)({}))
console.log(Set(abc)(1)(o))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment