com.github.mperry.fg.Lens.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionalgroovy-main Show documentation
Show all versions of functionalgroovy-main Show documentation
FunctionalGroovy enhances FunctionalJava for Groovy
package com.github.mperry.fg
import fj.F
import fj.F2
import fj.P
import fj.P2
import fj.Unit
import fj.data.Either
import fj.data.Option
import groovy.transform.TypeChecked
import groovy.transform.TypeCheckingMode
/**
* Created by MarkPerry on 14/01/14.
*/
@TypeChecked
class Lens {
F get
F2 set
@TypeChecked(TypeCheckingMode.SKIP)
static Lens lift(F g, F2 s) {
new Lens(g, s)
}
Lens(F g, F2 s) {
get = g
set = s
}
B get(A a) {
get.f(a)
}
A set(A a, B b) {
set.f(a, b)
}
A mod(A a, F f) {
set(a, f.f(get(a)))
}
State mod(F f) {
State.lift({ A a ->
def b = f.f(get(a))
P.p(set(a, b), b)
} as F)
}
State mod(Closure c) {
mod(c as F)
}
def Lens andThen(Lens lens) {
lens.compose(this)
}
@TypeChecked(TypeCheckingMode.SKIP)
def State map(F f) {
// WARNING: this is implemented differently from
// http://scalaz.github.io/scalaz/scalaz-2.9.1-6.0.4/doc.sxr/scalaz/Lens.scala.html
// I have the tuple in the opposite order, i.e. P.p(a, f.f(get(a)))
// I think this is ok as the trait States has the method "state"
// def state[S, A](f: S => (S, A)): State[S, A] = new State[S, A] {
// the order of the tuple returned by f is swapped compared to me
State.lift({ A a -> P.p(a, f.f(get(a)))} as F)
}
def State flatMap(F> f) {
State.lift({ A a -> f.f(get(a)).run(a)} as F)
}
@TypeChecked(TypeCheckingMode.SKIP)
def Lens compose(Lens lens) {
new Lens(
Functions.o(get, lens.get),
{ C c, B b -> lens.set(c, set(lens.get(c), b)) } as F2
)
}
@TypeChecked(TypeCheckingMode.SKIP)
def Lens, P2> product(Lens lens) {
new Lens(
{ P2 p -> P.p(get(p._1()), lens.get(p._2())) } as F,
{ P2 ac, P2 bd -> P.p(set(ac._1(), bd._1()), lens.set(ac._2(), bd._2())) } as F2
)
}
def Lens, B> sum(Lens lens) {
new Lens(
{ Either e ->
e.isLeft() ? get(e.left().value()) : lens.get(e.right().value())
} as F,
{ Either e, B b ->
e.isLeft() ? Either.left(set(e.left().value(), b)) : lens.set(e.right().value(), b)
} as F2
)
}
@TypeChecked(TypeCheckingMode.SKIP)
State update(B b) {
State.lift({ A a ->
P.p(set(a, b), b)
} as F)
}
State update(F f) {
update(f.f(Unit.unit()))
}
@TypeChecked(TypeCheckingMode.SKIP)
State state() {
State.lift({ A a -> P.p(a, get(a))} as F)
}
@TypeChecked(TypeCheckingMode.SKIP)
static Lens
© 2015 - 2024 Weber Informatics LLC | Privacy Policy