- use: implicits, types depends on each others, scala 2.x does not allow multiple implicits "brackets" for a trait
- ref: https://gigiigig.github.io/posts/2015/09/13/aux-pattern.html
// the trait
def foo[A, B, R](implicit foo: Foo.Aux[A, B], monoid: Monoid[R], ev: B =:= R): R = ???
// boilerplate for the Aux
trait Foo[A] {
type B
def bar: B
}
object Foo {
type Aux[A, B0] = Foo[A] { type B = B0 }
}
trait Monad[F[_]] {
def pure[A](a: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
pure(a).flatMap(f) === f(a)
m.flatMap(pure) === m
m.flatMap(g).flatMap(h) === m.flatMap(b => g(b).flatMap(h))
// definition
trait Show[A]{
def format(value: A): String
}
// implementations
object ShowInstances {
implicit val stringPrintable = new Show[String] {
def format(value: String) = "s show: " ++ value
}
implicit val stringPrintable = new Show[String] {
def format(value: Int) = "i show: " ++ value
}
}
- exposing through interface object
object Printer {
def format[A](value: A)
(implicit printer: Show[A]): String = {
printer.format(value)
}
def print[A](value: A)(implicit printer: Show[A]): Unit = {
println(format(input))
}
}
import ShowInstance._
Printer.print("foo") -> s show: foo
Printer.print(42) -> s show: 42
- exposing using type enrichement, c# extensions methods
object ShowSyntax {
implicit class ShowOps[A](value: A) {
def format[A](implicit printer: Show[A]): String = {
printer.format(value)
}
def print[A](implicit printer: Show[A]): Unit = {
println(format(input))
}
}
}
import ShowInstance._
"foo".print // = ShowOps("foo").print(impl. printer)
def f(x: Int): Option[Int] = if (x == 0) None else Some(x)
f(0) // None
f(1) // Some(2)
Pattern matching
match {
case 100 => "One hundred"
case _ => "Unknown value"
}
Initial Class Generic Value
class Default[A] {
val a: A = _
}