为什么我可以在这里使用地图功能?

时间:2015-12-23 10:01:13

标签: scala

我不明白为什么这段代码会编译:

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

如果我这样做:

val f: Int => Double = _.toDouble

然后lift(f)工作正常,但f map f会出错:error: value map is not a member of Int => Double

2 个答案:

答案 0 :(得分:2)

  

我不明白为什么这段代码会编译:

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

这是

的缩写
def lift[A,B](f: A => B): Option[A] => Option[B] = (o: Option[A]) => o map f 

方法lift返回一个函数:
- 需要Option[A]
- 使用某个函数f: A => B修改该选项的内容 - 返回结果Option[B]

因此,当您“解除”某些功能f: A => B时,您基本上将其从A => B升级为Option[A] => Option[B]。当这个新升级的功能被赋予o: Option[A]时,它会将该选项的内容映射到Option[B](通过使用原始功能升级时提供的f: A => B)。

  

如果我这样做:

val f: Int => Double = _.toDouble
     

然后提升(f)工作正常,但f map f给出错误error: value map is > not a member of Int => Double

是的,因为您无法映射功能。你只能使用函数来映射某些东西(顺便说一句,你可以映射的东西叫做仿函数)。

您想要做的是:

  1. 定义一些函数 f (您定义val f: Int => Double = _.toDouble
  2. 使用lift来“升级”您的功能f从Int => DoubleOption[Int] => Option[Double]
  3. 使用新升级的功能映射Option[Int],从而将其转换为Option[Double]
  4. 所以:

    val f: Int => Double = _.toDouble
    val upgraded = lift(f)
    println(upgraded(Some(8))) // prints Some(8.0)
    

答案 1 :(得分:1)

lift函数只是将函数f: A=> B提升到某个其他域上的函数,在这种情况下它是Option[_]。因此,lift的实施为您提供了一个函数f&#39 ;:选项[A] =>选项[B],因为选项具有map功能,您可以在第一个输入参数(这是'下划线')上调用它。

您不必致电f map f。你做的是解除你的f函数:

val f: Int => Double = _.toDouble
val lifted = lift(f)
lifted(Some(42)) //it should be Some(42.0)