Skip to content

Instantly share code, notes, and snippets.

sealed trait Hygiene extends Item
case class Shampoo(price: Double) extends Hygiene
case class ToothPaste(price: Double) extends Hygiene
object Cake {
implicit val price: Price[Cake] = new Price[Cake] {
def price(cake: Cake): Double = cake.price
}
}
object Apple {
val PricePerLb: Double = 3.0
implicit val price: Price[Apple] = new Price[Apple] {
def orderTotal(shoppingCart: List[Item]): Double = {
shoppingCart.foldLeft(0.0) { case (total, item) =>
total + implicitly[Price[Item]].price(item)
}
}
[error] ...could not find implicit value for parameter e: Price[Item]
[error] total + implicitly[Price[Item]].price(item)
[error] ^
object Item {
implicit val price: Price[Item] = new Price[Item] {
def price(item: Item): Double = item match {
case cake: Cake => Cake.price.price(cake)
case baguette: Baguette => Baguette.price.price(baguette)
case apple: Apple => Apple.price.price(apple)
case orange: Orange => Orange.price.price(orange)
case shampoo: Shampoo => Shampoo.price.price(shampoo)
case toothPaste: ToothPaste => ToothPaste.price.price(toothPaste)
}
import shapeless._
object PriceCompanion extends LabelledTypeClassCompanion[Price] {
object typeClass extends LabelledTypeClass[Price] {
def emptyProduct: Price[HNil] = new Price[HNil] {
def price(t: HNil) = 0.0
}
def product[F, T <: HList](name: String, sh: Price[F], st: Price[T]): Price[F :: T] = new Price[F :: T] {
def orderTotal(shoppingCart: List[Item]): Double = {
import PriceCompanion._
shoppingCart.foldLeft(0.0) { case (total, item) =>
total + implicitly[Price[Item]].price(item)
}
}
val shoppingCart: List[Item] = List(
Orange(0.25),
Orange(0.33),
Apple(0.22),
Apple(0.27),
Apple(0.30),
Baguette(2),
ToothPaste(4)
)
val shoppingCart: List[Fruit] = List(
Orange(0.25),
Orange(0.33),
Apple(0.22),
Apple(0.27),
Apple(0.30)
)
orderTotal(shoppingCart) // 4.69