Skip to content

Instantly share code, notes, and snippets.

val (x, y, z) = (1.eur, 2.eur, 3.eur)
test("associativity") {
assert(((x |+| y) |+| z) == (x |+| (y |+| z)))
}
test("left identity") {
assert((Monoid.empty |+| x) == x)
}
implicit def monoidInstanceForFastMoney: Monoid[FastMoney] = new Monoid[FastMoney] {
override def empty: FastMoney = FastMoney.of(0, "EUR")
override def combine(x: FastMoney, y: FastMoney): FastMoney = x add y
}
import cats.kernel.Monoid
import cats.syntax.monoid._
type Quantity = Int
type Pricer[A] = Quantity => (Quantity, A)
def total[A: Monoid](pricings: List[(Quantity, List[Pricer[A]])]): A = {
pricings.foldLeft(Monoid[A].empty) { case (grandTotal, (quantity, pricers)) =>
grandTotal |+| total(quantity, pricers)
}
case class Pricing(val quantity: Int, val unitPrice: UnitPrice, val tierPrice: TierPrice)
case class UnitPrice(val price: BigDecimal)
case class TierPrice(val price: BigDecimal, val quantity: Int)
def total(croissants: Pricing, baguettes: Pricing): BigDecimal = {
val croissantTotal = total(croissants)
val baguetteTotal = total(baguettes)
type Quantity = Int
type Amount = BigDecimal
type Pricer = Quantity => (Quantity, Amount)
def total(pricings: List[(Quantity, List[Pricer])]): Amount = {
pricings.foldLeft(BigDecimal(0)) { case (grandTotal, (quantity, pricers)) =>
grandTotal + total(quantity, pricers)
}
}
val pricers = List(priceByTier, priceByUnit)
val (_, total) = pricers.foldLeft((quantity, BigDecimal(0))) {
case ((quantity, total), pricer) =>
val (remainingQuantity, amount) = pricer(quantity)
(remainingQuantity, total + amount)
}
total
type Quantity = Int
type Amount = BigDecimal
private def total(quantity: Quantity, tierPrice: TierPrice, unitPrice: UnitPrice): Amount = {
val priceByTier: Quantity => (Quantity, Amount) = { quantity =>
val tiers = quantity / tierPrice.quantity
val tierPriceAmount = tiers * tierPrice.price
val remainingQuantityAfterTierPrice = quantity % tierPrice.quantity
(remainingQuantityAfterTierPrice, tierPriceAmount)
}
private def total(quantity: Int, tierPrice: TierPrice, unitPrice: UnitPrice): BigDecimal = {
// initial value
var total = BigDecimal(0)
// iteration 1 - tier price
val tiers = quantity / tierPrice.quantity
val tierPriceAmount = tiers * tierPrice.price
// accumulator to pass to the iteration 2
val remainingQuantityAfterTierPrice = quantity % tierPrice.quantity
total = total + tierPriceAmount
def total(pricings: List[Pricing]): BigDecimal =
pricings.foldLeft(BigDecimal(0)) { (grandTotal, pricing) =>
grandTotal + total(pricing)
}
def total(croissants: Pricing, baguettes: Pricing, breadRolls: Pricing): BigDecimal = {
val initialTotal = BigDecimal(0)
val croissantsTotal = initialTotal + total(croissants)
val baguettesTotal = croissantsTotal + total(baguettes)
baguettesTotal + total(breadRolls)
}