case class Product(money: Int)
case class Coins(gohyakuen: Int, hyakuen: Int, gojuen: Int, juen: Int) {
def +(other: Coins) = Coins(gohyakuen + other.gohyakuen, hyakuen + other.hyakuen, gojuen + other.gojuen, juen + other.juen)
def sum(): Int = gohyakuen * 500 + hyakuen * 100 + gojuen * 50 + juen * 10
}
implicit val monoidCoins = new Monoid[Coins] {
override def empty: Coins = Coins(0, 0, 0, 0)
override def combine(x: Coins, y: Coins): Coins = x + y
}
def buyProduct(coins: Coins): Writer[Coins, Product] =
for {
_ <- Writer.tell(coins)
r <- Writer.value[Coins, Product](Product(coins.sum()))
} yield r
def buyProducts(coinsList: List[Coins]): Writer[Coins, List[Product]] =
coinsList.map(buyProduct).sequence
println(buyProducts(List(Coins(0, 1, 2, 3), Coins(1, 2, 0, 1), Coins(2, 0, 3, 2))).run)