-
Notifications
You must be signed in to change notification settings - Fork 348
/
lens.scala
50 lines (34 loc) · 1.2 KB
/
lens.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// Copyright (c) 2013-2018 Rob Norris and Contributors
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT
package doobie.util
import cats.data.State
// embarrassigly minimal lens implementation to avoid a lib conflict
object lens {
final case class Lens[A, B](get: A => B, set: (A, B) => A) {
def andThen[C](bc: Lens[B, C]): Lens[A, C] =
Lens(a => bc.get(get(a)), (a, c) => set(a, bc.set(get(a), c)))
def >=>[C](bc: Lens[B, C]): Lens[A, C] =
andThen(bc)
def compose[C](bc: Lens[C, A]): Lens[C, B] =
bc andThen this
def modify(a: A, f: B => B): A =
set(a, f(get(a)))
def xmapA[AA](f: AA => A, g: A => AA): Lens[AA, B] =
Lens(aa => get(f(aa)), (aa, b) => g(set(f(aa), b)))
def xmapB[BB](f: BB => B, g: B => BB): Lens[A, BB] =
Lens(a => g(get(a)), (a, bb) => set(a, f(bb)))
def mods(f: B => B): State[A, B] =
State { a =>
val b = get(a)
val bʹ = f(b)
val aʹ = set(a, bʹ)
(aʹ, bʹ)
}
def %=(f: B => B): State[A, B] =
mods(f)
def :=(b: => B): State[A, B] =
mods(_ => b)
}
type @>[A,B] = Lens[A,B]
}