Skip to content

Instantly share code, notes, and snippets.

@aryairani
Last active August 29, 2015 14:02
Show Gist options
  • Save aryairani/7588fbfedb75c0c927a7 to your computer and use it in GitHub Desktop.
Save aryairani/7588fbfedb75c0c927a7 to your computer and use it in GitHub Desktop.
/* The Scalaz version would look something like this: */
import scalaz.Lens.lensg
val bandNameL = lensg[Band, String](b => n => b.copy(name = n), _.name)
val guitarTuningL = lensg[Guitar, String](g => t => g.copy(tuning = t), _.tuning)
// KeyedLens #1: Here Person is a key.
def guitarL(p: Person) = lensg[Band, Guitar](
b => newValue => b.copy(members = b.members + (p -> newValue)),
b => b.members(p))
// KeyedLens #2: Here Int is the key.
def stringGaugeL(s: Int) = lensg[Guitar, Double](
g => newValue => g.copy(gauges = g.gauges.updated(s - 1, newValue)),
g => g.gauges(s - 1))
// Compose a keyed and non-keyed lens
def guitaristsTuningL(p: Person) = guitarL(p) >=> guitarTuningL
// Compose 2 keyed lenses
def guitaristsGaugeL(p: Person, s: Int) = guitarL(p) >=> stringGaugeL(s)
/*
You get these types:
bandNameL: Lens[Band,String]
guitarTuningL: Lens[Guitar,String]
guitarL: (p: Person)Lens[Band,Guitar]
stringGaugeL: (s: Int)Lens[Guitar,Double]
guitaristsTuningL: (p: Person)LensFamily[Band,String]
guitaristsGaugeL: (p: Person, s: Int)LensFamily[Band,Double]
The usage looks like:
*/
guitaristsTuningL(acle).get(band)
guitaristsGaugeL(acle, 7).get(band)
guitaristsTuningL(acle).set(band, "G#FA#D#FA#D#")
guitaristsGaugeL(acle, 7).set(band, 0.0666666)
/* ...which IMO is not as pretty pretty as David's solution,
since the arguments are split up.
But if you are writing it in a State comprehension, the scalaz
version works nicely; but I don't think the KeyedLens version will.
Here's what the scalaz version could look like: */
val changeAcleS = for {
oldTuning <- guitaristsTuningL(acle).st
old7Gauge <- guitaristsGaugeL(acle, 7).st
_ <- guitaristsTuningL(acle) := "G#FA#D#FA#D#"
_ <- guitaristsGaugeL(acle, 7) := 0.0666666
} yield (oldTuning, old7Gauge)
/* alternatively: */
val changeAcleS2 = for {
oldTuning <- guitaristsTuningL(acle) <:= "G#FA#D#FA#D#"
old7Gauge <- guitaristsGaugeL(acle, 7) <:= 0.0666666
} yield (oldTuning, old7Gauge)
/* or */
val changeAcleS3 = for {
_ <- guitaristsTuningL(acle) := "G#FA#D#FA#D#"
_ <- guitaristsGaugeL(acle, 7) := 0.0666666
} yield ()
// save all
val (updatedBand, (oldTuning, old7Gauge)) = changeAcleS(band)
// save updated band, discard old values
val bandOnly = changeAcleS3.exec(band)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment