Last active
May 24, 2020 11:08
-
-
Save venil7/eef3f989a9eea8712e76102a9357d2e0 to your computer and use it in GitHub Desktop.
Functional Lense implementation in TypeScript
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
type LGetter<LFrom, LTo> = (f: LFrom) => LTo; | |
type LSetter<LFrom, LTo> = (t: LTo, f: LFrom) => LFrom; | |
type LUpdater<T> = ((t: T) => T); | |
type LModifier<LFrom, LTo> = (u: LUpdater<LTo>) => (f: LFrom) => LFrom; | |
class Lense<LFrom, LTo> { | |
constructor(private get: LGetter<LFrom, LTo>, private set: LSetter<LFrom, LTo>) { } | |
public compose<LTo2>(inner: Lense<LTo, LTo2>): Lense<LFrom, LTo2> { | |
const _get: LGetter<LFrom, LTo2> = (f: LFrom) => inner.get(this.get(f)); | |
const _set: LSetter<LFrom, LTo2> = (t2: LTo2, f: LFrom) => this.set(inner.set(t2, this.get(f)), f); | |
return new Lense(_get, _set); | |
} | |
public reader: () => LGetter<LFrom, LTo> = () => this.get; | |
public writer: () => LSetter<LFrom, LTo> = () => this.set; | |
public modify: LModifier<LFrom, LTo> = updater => f => | |
this.set(updater(this.get(f)), f); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how to use lenses
first lets define some types that hierarchically relate to one another
then we define values with those types
and finally we define
lenses
that zoom in one level at a time. Skipping levels in alense
is possible, but defeats the purpose, as we will see later - main property of lenses iscomposability
, and we will be able to skip levels by composing different lenses.zoom in read
then we compose lenses, to define derived lenses that zoom from very large to very small
zoom in modify
or we can compose a lense and get modifier that would modify a deep nested property