0

I have data types:

import cats.Monoid
import cats.implicits._

object Domain {
  case class Money(amount: Double) extends AnyVal {}

  implicit val moneyMonoid = new Monoid[Money] {
    override def combine(a: Money, b: Money): Money = Money(a.amount + b.amount)
    override def empty: Money                       = Money(0)
  }

  case class Operation(account: Account, amount: Money) extends AnyRef
  type Operations = List[Operation]
}

I want to implement totalAmountCalculation like function composition

val calcTotalAmount = map(x => x.amount) >>> combineAll

For this I wrote some code:

def map[A, B](F: A => B): List[A] => List[B] = (m: List[A]) => m.map(F) 
val combineAll      = moneyMonoid.combineAll _

val calcTotalAmount = map[Operation, Money](x => x.amount) >>> combineAll

What cats features I can use for avoid write Monad wrapper for use it in functions composition ?

I want to see my code like:

map(x => x + 1) >>>
filter(x < 100) >>> 
fold(1)((a,b) => a+b))
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
nonlux
  • 774
  • 2
  • 6
  • 20

1 Answers1

1

If I understood your question correctly, you want to avoid using the wrapper Amount and having to use x => x.amount everywhere in your function definitions.

There are a couple of ways to solve that problem. The first would be to use a type alias, as you did for operations. This will naturally give you the default Monoid[Int] which has 0 for zero and addition for combine:

allMoney
 .map(_ + 1.0)
 .filter(_ > 3.0)
 .foldLeft(1.0)(_ + _)

// 13.0

allMoney.combineAll

// 12.0

Another option would be to use the newtype library which gives a similar effect using case classes:

@newsubtype case class Money(amount: Double)

allMoney
  .map(_ + 1.0)
  .filter(_ > 3.0)
  .foldLeft(1.0)(_ + _)

// 13.0
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321