dca*_*tro 5 monads functional-programming scala combinators higher-order-functions
implicit class KComb[A](a: A) {
def K(f: A => Any): A = { f(a); a }
}
Run Code Online (Sandbox Code Playgroud)
鉴于 K 组合器的这种实现,我们可以在应用副作用的同时链接一个值的方法调用,而无需临时变量。例如:
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
Run Code Online (Sandbox Code Playgroud)
现在,我需要做一些类似的事情,但改用 IO monad。
def getDocument: IO[Document] = ???
def print(d: Document): IO[Unit] = ???
def process(d: Document): IO[Result] = ???
Run Code Online (Sandbox Code Playgroud)
我的问题是:此操作的组合器是否已经存在?Scalaz 或其他一些库中是否有任何东西可以做到这一点?
我找不到任何东西,所以我K自己为 monad推出了这个组合器的变体。我tapM之所以这样称呼它,是因为 1)tap在 Ruby 和unsafeTapScalaz 中调用了 K 组合器,以及 2) Scalaz 似乎遵循了附加M到众所周知的方法的monadic变体(例如foldLeftM, foldMapM, ifM, untilM, whileM)的模式。
但我仍然想知道是否已经存在类似的东西,我只是在重新发明轮子。
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
Run Code Online (Sandbox Code Playgroud)
编辑:我最初的答案被误导了。这是正确的。
在 cats 和scalaz中都有flatTapon 方法。FlatMap>>!BindOps
getDocument flatTap print >>= process
getDocument >>! print >>= process
Run Code Online (Sandbox Code Playgroud)
编辑^2:更改flatMap为>>=更容易显示点击和绑定之间的关系。