Skip to content

Instantly share code, notes, and snippets.

@orium
Last active June 14, 2019 14:25
Show Gist options
  • Save orium/30d3e740143da24484407f21e7cfee00 to your computer and use it in GitHub Desktop.
Save orium/30d3e740143da24484407f21e7cfee00 to your computer and use it in GitHub Desktop.
Scala workshop 20181017 — UriCodecs, Quicklens, Aux pattern
object UriCodecsDemo extends App {
import UriEncoder.Implicit._
case class Channel(name: String)
implicit val channelUriEncoder: UriEncoder[Channel] = _.name
val uri = (SimpleUri(HttpProtocol.Https, "discovery.itv.com") / "channel" / Channel("itv")) ? ("q" -> "foobar") ? ("lang" -> "en")
println(uri.fullPath)
implicit val countryDecoder: UriDecoder.Aux[Channel, String] = UriDecoder {
case "ITV" | "itv" => Right(Channel("itv"))
case "ITV2" | "itv2" => Right(Channel("itv2"))
case c => Left(s"Unknown channel $c")
}
println(UriDecoder.decode[Channel]("itv"))
}
object QuickLensDemo extends App {
import com.softwaremill.quicklens._
case class Person(name: String)
sealed trait Engine {
def power: Int
}
object Engine {
case class Jet(power: Int) extends Engine
case class WarpDrive(power: Int) extends Engine
}
case class Spaceship(
name: String,
captain: Person,
engines: Seq[Engine]
)
val spaceship = Spaceship(
name = "USS Enterprise",
captain = Person(name = "Kirk"),
engines = Seq(
Engine.WarpDrive(power = 30),
Engine.Jet(power = 10),
Engine.WarpDrive(power = 30),
)
)
val newSpaceship = spaceship.modify(_.name).using(_.toUpperCase)
println(newSpaceship)
/*
val newSpaceship = spaceship.modify(_.name).using(_.toUpperCase)
val newSpaceship = spaceship.modify(_.name).setTo("Deathstar")
val newSpaceship = spaceship.modify(_.captain.name).setTo("Frodo")
val newSpaceship = spaceship.modifyAll(_.name, _.captain.name).using(_ + "!!!")
val newSpaceship = spaceship.modify(_.engines.each.power).using(_ * 2)
val newSpaceship = spaceship.modify(_.engines.at(1).power).using(_ * 2)
val newSpaceship = spaceship.modify(_.engines.each.when[Engine.WarpDrive].power).using(2 * _)
val personNameLens = modify(_: Person)(_.name)
val spaceshipCaptainLens = modify(_: Spaceship)(_.captain)
val spaceshipCaptainNameLens = spaceshipCaptainLens andThenModify personNameLens
val newSpaceship = spaceshipCaptainNameLens(spaceship).using("James " + _ )
*/
}
object AuxPattern extends App {
// Exameple from https://stackoverflow.com/questions/43900674/understanding-the-aux-pattern-in-scala-type-system
trait Last[Tuple] {
type LastType
def last(t: Tuple): LastType
}
object Last {
type Aux[T, L] = Last[T] { type LastType = L }
}
implicit def lastForPair[A, B]: Last[(A, B)] { type LastType = B } = new Last[(A, B)] {
type LastType = B
def last(t: (A, B)): B = t._2
}
implicit def lastForTriple[A, B, C]: Last[(A, B, C)] { type LastType = C } = new Last[(A, B, C)] {
type LastType = C
def last(t: (A, B, C)): C = t._3
}
def getLast[T](t: T)(implicit lastEvidence: Last[T]): lastEvidence.LastType =
lastEvidence.last(t)
val l0: Double = getLast(("", 1, .1))
val l1: Int = getLast(("", 1))
println(l0)
println(l1)
// Doesn't work:
// def sortByLastWrong[T](s: Seq[T])(implicit lastEvidence: Last[T], ordering: Ordering[lastEvidence.LastType]): Seq[T] =
// ???
def sortByLast[T, L](s: Seq[T])(implicit lastEvidence: Last.Aux[T, L], ordering: Ordering[L]): Seq[T] =
s.sortBy(getLast(_))
val seq = Seq((0, "b"), (0, "a"))
val seq2 = Seq((0, 4, "b"), (0, 4, "a"))
println(sortByLast(seq))
println(sortByLast(seq2))
// We don't truly need `Aux`, it just makes things more readable:
def sortByLastAlsoOk[T, L](s: Seq[T])(implicit lastEvidence: Last[T] { type LastType = L }, ordering: Ordering[L]): Seq[T] =
s.sortBy(getLast(_))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment