Skip to content

Instantly share code, notes, and snippets.

@tusharmath
Created August 20, 2017 09:17
Show Gist options
  • Save tusharmath/205624ab2e3f55c5fe2c675384dd34cc to your computer and use it in GitHub Desktop.
Save tusharmath/205624ab2e3f55c5fe2c675384dd34cc to your computer and use it in GitHub Desktop.
const Set = (lens, value, target) => lens.set(value, target)
const View = (lens, target) => lens.get(target)
const Over = (lens, func, target) =>
Set(lens, func(View(lens, target), target), target)
const Compose = (...lenses) => {
lenses = lenses.reverse()
const itar = (i, target, value) => {
if (i === lenses.length) return value
return lenses[i].set(itar(i + 1, lenses[i].get(target), value), target)
}
return {
__isLens: true,
get: state => lenses.reduce((state, i) => i.get(state), state),
set: (value, target) => itar(0, target, value)
}
}
const Identity = () => ({
__isLens: true,
get: target => target,
set: (focus, target) => target
})
const Focus = (...args) => {
if (args.length === 0) return Identity
if (args.length === 1) {
const o = args[0]
if (o.constructor === Array) return Compose.apply(null, o.map(l => Focus(l)))
if (o.constructor === Number) return Index(o)
if (o.constructor === String) return Prop(o)
if (o.constructor === Function) return Where(o)
if (o.__isLens) return o
}
if (args.length > 1) return Focus(args)
return Identity
}
const Prop = name => ({
__isLens: true,
get (target) {
return target[name]
},
set (value, target) {
return { ...target, [name]: value }
}
})
const Index = id => ({
__isLens: true,
get (target) {
return target[id]
},
set (value, target) {
return target.map((k, i) => (i === id ? value : k))
}
})
const Where = pred => ({
__isLens: true,
get (target) {
const el = target.find(pred)
if (el === undefined) throw Error('Lens[Where] could not find any element')
return el
},
set (value, target) {
return target.map((k, i) => (pred(k) ? value : k))
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment