Skip to content

Instantly share code, notes, and snippets.

@povilas
Last active July 14, 2018 10:01
Show Gist options
  • Save povilas/d6d35c418c3bf9025da622a2b169a4a0 to your computer and use it in GitHub Desktop.
Save povilas/d6d35c418c3bf9025da622a2b169a4a0 to your computer and use it in GitHub Desktop.
case class Rectangle(width: Double, height: Double)
case class Square(radius: Double)
case class Triangle(side: Double)
trait Area[A] {
def area(shape: A): Double
}
object Area {
def apply[A: Area]: Area[A] = implicitly[Area[A]]
def instance[A](f: A => Double): Area[A] = new Area[A] {
override def area(shape: A): Double = f(shape)
}
implicit val rectangleArea: Area[Rectangle] = instance(_ => 1)
implicit val squareArea: Area[Square] = instance(_ => 2)
implicit val triangleArea: Area[Triangle] = instance(_ => 3)
}
sealed trait ShapeEx {
type Inner
val value: Inner
val evidence: Area[Inner]
def area: Double = evidence.area(value)
}
object ShapeEx {
implicit def mkShapeEx[A: Area](a: A): ShapeEx = ShapeBox(a)
}
case class ShapeBox[A](value: A)(implicit val evidence: Area[A])
extends ShapeEx { type Inner = A }
val shapes: List[ShapeEx] = List(Rectangle(1, 2), Square(3), Triangle(4))
val totalArea = shapes.foldLeft(0.0)(_ + _.area)
assert(totalArea == 6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment