当你拥有andThen时,在函数上映射很有用

thl*_*lim 8 scala scalaz

使用Scalaz,函数可以映射到另一个函数.什么时候我会想使用mapandThen?使用有明显的优势map吗?谢谢

例如,

val f: Int => Int = (a) => a + 10

val g: Int => Int = (a) => a * 100

(f map g map {_*3})(10) == (f andThen g andThen {_*3})(10)  // true
Run Code Online (Sandbox Code Playgroud)

Tra*_*own 12

暂时搁置实现细节,map andThen针对函数(在函数实例下A => ?),如果我们专门讨论函数而不是更高级函数,那么谈论优先于其他函数并不是很有意义.抽象程度.

map(和Functor更普遍的类型类)允许我们做的是什么方法是抽象的特定类型或类型构造函数.假设我们要编写一个incrementResult使用这两种方法工作A => Int或者Kleisli[Option, A, Int],例如.这些类型没有在继承方面的任何共同点(短的AnyRef,这是无用的),但A => ?Kleisli[Option, A, ?]都是仿函数,所以我们可以这样写:

import scalaz._, Scalaz._

def incrementResult[F[_]: Functor](f: F[Int]): F[Int] = f.map(_ + 1)
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它(注意我使用kind-projector来简化类型语法):

scala> val plainOldFuncTriple: Int => Int = _ * 3
plainOldFuncTriple: Int => Int = <function1>

scala> val optionKleisliTriple: Kleisli[Option, Int, Int] = Kleisli(i => Some(i * 3))
optionKleisliTriple: scalaz.Kleisli[Option,Int,Int] = Kleisli(<function1>)

scala> val f = incrementResult[Int => ?](plainOldFuncTriple)
f: Int => Int = <function1>

scala> val k = incrementResult[Kleisli[Option, Int, ?]](optionKleisliTriple)
k: scalaz.Kleisli[Option,Int,Int] = Kleisli(<function1>)

scala> f(10)
res0: Int = 31

scala> k(10)
res1: Option[Int] = Some(31)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,特别是有更好的方法来实现这个操作,但它显示了一般的想法 - 我们不能编写一个适用于普通函数和Kleisli箭头使用的方法andThen,但我们可以使用额外的抽象级别map给出我们.

因此,要回答你的问题-你会用map,如果你想在抽象有一个仿函数实例的所有类型构造,但如果你有专门职能部门紧密合作,map andThen和-只要我们还在留出实施细则 - 你选择哪个并不重要.


脚注:mapScalaz的syntax包为您提供了具有functor实例的类型的值作为扩展方法实现,因此在使用map而不是andThen在函数上涉及一小部分开销(在编译时和运行时).如果你只是在处理函数而不需要额外的抽象,那么你也可以选择andThen.