Last active
January 10, 2016 11:17
-
-
Save gvergnaud/30bd72f4c6bd35cd015d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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