Skip to content

Instantly share code, notes, and snippets.

@aoiroaoino
Last active August 29, 2015 14:07
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 aoiroaoino/7c7b1ec1ec0e71ed37a1 to your computer and use it in GitHub Desktop.
Save aoiroaoino/7c7b1ec1ec0e71ed37a1 to your computer and use it in GitHub Desktop.
MyLens
scala> :paste
object MyLens {
trait Lens[A, B] {
self =>
def get(a: A): B
def set(a: A, b: B): A
def modify(f: B => B, a: A): A
def compose[C](that: Lens[C, A]) = new Lens[C, B] {
def get(c: C): B = self.get(that.get(c))
def set(c: C, b: B): C = that.set(c, self.set(that.get(c), b))
def modify(f: B => B, c: C) = that.set(c, self.set(that.get(c), f(self.get(that.get(c)))))
}
}
def mkLens[A, B](setter: (A, B) => A, getter: A => B) = new Lens[A, B] {
def get(a: A): B = getter(a)
def set(a: A, b: B): A = setter(a, b)
def modify(f: B => B, a: A): A = setter(a, f(getter(a)))
}
}
// --- Position Lens
val xLens = MyLens.mkLens[Position, Int]((pos, _x) => pos.copy(x = _x), _.x)
val yLens = MyLens.mkLens[Position, Int]((pos, _y) => pos.copy(y = _y), _.y)
// --- Player Lens
val nameLens = MyLens.mkLens[Player, String]((pl, n) => pl.copy(name = n), _.name)
val positionLens = MyLens.mkLens[Player, Position]((pl, pos) => pl.copy(position = pos), _.position)
// --- Compose
val pxLens = xLens compose positionLens
val pyLens = yLens compose positionLens
// --- Example
case class Position(x: Int, y: Int)
case class Player(name: String, position: Position)
val startPosition = Position(0, 1)
val player = Player("Aoino", startPosition)
scala> xLens.get(startPosition)
res0: Int = 0
scala> yLens.set(startPosition, 100)
res1: Position = Position(0,100)
scala> nameLens.modify("Aoiro" + _, player)
res2: Player = Player(AoiroAoino,Position(0,1))
scala> pxLens.get(player)
res3: Int = 0
scala> pyLens.set(player, 100)
res4: Player = Player(Aoino,Position(0,100))
scala> pyLens.modify(_ * 20, player)
res5: Player = Player(Aoino,Position(0,20))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment