Skip to content

Instantly share code, notes, and snippets.

@gvergnaud
Last active January 10, 2016 11:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gvergnaud/30bd72f4c6bd35cd015d to your computer and use it in GitHub Desktop.
Save gvergnaud/30bd72f4c6bd35cd015d to your computer and use it in GitHub Desktop.
import { compose, curry, map } from 'ramda'
import Const, { getConst } from './functors/Const'
import Identity, { runIdentity } from './functors/Identity'
import K from './functors/K'
/* ----------------------------------------- *
Lenses définition
* ----------------------------------------- */
// objectLens :: String -> Functor f -> Object -> f Object
const objectLens = curry((key, f, obj) => map(value => ({
...obj,
[key]: value
}), f(obj[key])))
// num :: Number -> Functor f -> [x] -> f [x]
const num = curry((index, f, arr) => map(value => [
...arr.split(0, index),
value,
...arr.split(index + 1)
], f(arr[index])))
/* ----------------------------------------- *
The 3 methods
* ----------------------------------------- */
// s = data structure
// a = value of a specific key or index
// Lens s a = Lens of a defined data structure (Object, Array...) and a defined key or index
// view :: Lens s a -> s -> a
const view = curry((lens, x) => compose(getConst, lens(Const.of))(x))
// over :: Lens s a -> (a -> a) -> s -> s
const over = curry((lens, f, x) => compose(runIdentity, lens(compose( Identity.of, f )))(x))
// set :: Lens s a -> a -> s -> s
const set = curry((lens, v, x) => over(lens, K(v), x))
/* ----------------------------------------- *
Let's play
* ----------------------------------------- */
const user = { name: 'Gabriel', age: 22, friends: [{ name: 'Stachmou' }, { name: 'HugoGuiillouu' }] }
const L = {}
L.name = objectLens('name')
L.friends = objectLens('friends')
// lenses compose left to right
L.secondFriendName = compose(L.friends, num(1), L.name)
console.log(view(L.name, user))
// => Gabriel
console.log(view(L.secondFriendName, user))
// => HugoGuiillouu
console.log(over(L.name, (name) => `${name} Vergnaud`, user))
// => { name: 'Gabriel Vergnaud', age: 22, friends: [...] }
console.log(set(L.name, 'Gabz', user))
// => { name: 'Gabz', age: 22, friends: [...] }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment