implicit class KComb[A](a: A) {
def K(f: A => Any): A = { f(a); a }
}
Given this implementation of the K combinator, we can chain method calls on a value while applying side effects, without the need for temp variables. E.g.:
case class Document()
case class Result()
def getDocument: Document = ???
def print(d: Document): Unit = ???
def process(d: Document): Result = ???
val result = process(getDocument.K(print))
// Or, using the thrush combinator
// val result = getDocument |> (_.K(print)) |> process
Now, I need to do something similar, but using the IO monad instead.
def getDocument: IO[Document] = ???
def print(d: Document): IO[Unit] = ???
def process(d: Document): IO[Result] = ???
My question is: does a combinator for this operation exist already? Is there anything in Scalaz, or maybe some other library, that does this?
I couldn't find anything, so I rolled out this variant of the K combinator for monads myself.
I called it tapM because 1) the K combinator is called tap in Ruby and unsafeTap in Scalaz and 2) it seems Scalaz follows the pattern of appending M to monadic variants of well known methods (e.g. foldLeftM, foldMapM, ifM, untilM, whileM).
But I'd still like to know if anything of the sort exists already and I'm just reinventing the wheel.
implicit class KMonad[M[_]: Monad, A](ma: M[A]) {
def tapM[B](f: A => M[B]): M[A] =
for {
a <- ma
_ <- f(a)
} yield a
}
// usage
getDocument tapM print flatMap process
Edit: My initial answer was misguided. Here's the correct one.
There's a flatTap method on FlatMap in cats and >>! on BindOps in scalaz.
getDocument flatTap print >>= process
getDocument >>! print >>= process
Edit^2: Changed flatMap to >>= to more easily show the relationship between tap and bind.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With