与标识映射并应用副作用的模式

Pattern for mapping with identity and applying a side-effect

是否有更清晰的方式表达以下模式:

def getUser(id: String): Option[User] = ???

getUser("12345").map { user =>
  someSideEffect(user)
  user
}

注意给定一个仿函数,我们如何使用恒等函数进行映射,同时也将副作用函数应用于盒装值。

Future.andThen 正是这样做的:

Applies the side-effecting function to the result of this future, and returns a new future with the result of this future.

是否有类似 Future.andThen 但在一般情况下适用于任何函子的东西?

没有开箱即用的东西。人们经常用这样的东西来添加它:

 object ImplicitUtils {
    implicit class Utils[T](val t: T) extends AnyVal {
       def tap(f: T => Unit): T = { f(t) ; t }
    }
 }

所以,现在你可以写:

 import ImplicitUtils._
 val user = getUser("foo").tap(someSideEffect)
object FunctorAndThen {

  import cats.Functor
  import cats.implicits._
  import scala.language.higherKinds

  implicit class AndThen[F[_], A](val f: F[A])(implicit ev: Functor[F]) {
    def andThen(sideEffect: A => Unit): F[A] = {
      f.map(sideEffect)
      f
    }
  }
}

// Usage:

import FunctorAndThen._
import cats.implicits._

val result: Option[String] = Option("a").andThen(a => println(a))
println(result)

Scala 2.13 开箱即用 tap

import scala.util.chaining._
Some(42) tap println

cats companion mouse 有它作为 <|

import mouse.all._
Some(42) <| println

两者都输出

Some(42)
res1: Some[Int] = Some(42)

在 cats 回购 Kestrel combinator for Monad/Functor #1559flatTap 而非 tap 的规定中存在关于此主题的已解决问题。