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