Scala中的管道功能(合并地图和然后)

时间:2014-09-19 09:29:12

标签: scala

在Scala中管理内容通常非常简单 - 对于集合,mapcompose function composition,请考虑andThen

但是,我似乎找不到将两者结合起来的方法。我有一个返回Option[Double]的函数。我希望过滤Double值(降低其精度),如果它在那里。 andThen已接近但需要我处理选项。

在Scala 2.11中有没有一个很好的内置方法来处理它?<​​/ p>

class Temp( ff: (Object) => Option[Double] )

object Temp {

  def apply( f: (Object) => Option[Double] ) = {

    def cutTo5Digits(v: Double): Double = {
      v - (v % 1e-5)
    }

    // call 'f', then pipe its output (if some) via 'cutTo5Digits'?
    //
    //new Temp( f map cutTo5Digits )    // nope
    //new Temp( f _ andThen cutTo5Digits _ )   // would need option unwrapping

    new Temp((o: Object) => f(o) map ((v: Double) => cutTo5Digits(v)))  // compiles
  }
}

2 个答案:

答案 0 :(得分:2)

我认为最好的解决方案是new Temp(f(_) map cutTo5Digits),它有什么问题?

但是如果你想要这样的语法:f map cutTo5Digits,那么你可以使用scalaz中的Kleisli,其中f的类型为Kleisli[Option, Object, Double],即:

def apply( f: (Object) => Option[Double] ) = {
    def cutTo5Digits(v: Double): Double = v - (v % 1e-5)
    val ff = Kleisli(f)
    new Temp(ff map cutTo5Digits) // or inline Kleisli(f) map ...
  }

或者您也可以cutTo5Digits类型为Double => Option[Double],此类函数可以使用Kliesli >=>方法进行链接,您可以将其重写为ff >=> cutTo5Digits

答案 1 :(得分:2)

如果您想使用andThen语法,可以将函数升级为仿函数,例如:

def liftOption[A, B](f: A => B): Option[A] => Option[B] = _.map(f(_))

要突出显示功能组成,您现在可以写:

(f _) andThen liftOption(cutTo5Digits _)

如果您隐式进行此转换,您甚至可以使用原始f _ andThen cutTo5Digits _。如果您使用的是Scalaz,则应该可以通过cutTo5Digits.lift[Option]解除功能。