【问题标题】:Pattern for mapping with identity and applying a side-effect使用身份进行映射并应用副作用的模式
【发布时间】:2018-07-17 05:14:50
【问题描述】:

下面的模式有没有更清晰的表达方式:

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

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

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

Future.andThen 正是这样做的:

将副作用函数应用于这个未来的结果,并且 用这个未来的结果返回一个新的未来。

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

【问题讨论】:

    标签: scala monads side-effects


    【解决方案1】:

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

     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)
    

    【讨论】:

      【解决方案2】:

      Scala 2.13 以tap 开箱即用地提供它

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

      猫伴侣mouse 将其命名为<|

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

      两者都输出

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

      在猫回购 Kestrel combinator for Monad/Functor #1559 和提供 flatTap 但不是 tap 中存在关于此主题的已关闭问题。

      【讨论】:

        【解决方案3】:
        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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-08-04
          • 2023-02-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多