Scala-不为理解而编译

时间:2018-08-23 09:18:26

标签: scala functional-programming for-comprehension

我正在尝试运行以下代码:

def split(input: Int): List[Int] = {
  val inputAsString = input.toString
  val inputAsStringList = inputAsString.split("").toList
  inputAsStringList.map(_.toInt).reverse
}

split(3122)

def increment(list: List[Int]): List[Int] = {
  def loop(multiplier: Int, result: List[Int], list: List[Int]): List[Int] = list match {
    case x :: xs =>
      val newList = (x * multiplier) :: result
      loop(multiplier * 10, newList, xs)
    case Nil => result
  }

  loop(1, List(), list)
}

val result: List[Int] = for {
  splited <- split(3122)
  incremented <- increment(splited)
} yield incremented

但是incremented <- increment(splited)行给出了以下错误:

  

类型不匹配,预期:List [Int],实际:Int

如果两个函数都返回相同的数据类型,为什么会发生这种情况?

2 个答案:

答案 0 :(得分:2)

您的increment函数使用一个List[Int],但是在理解时splited是一个Int。这是因为在splited <- split(3122)行中,您实际上是在说for every x: Int in split(y): List[Int]。如果要编译,则希望val result代码看起来像这样:

...
val splited = split(3122)

val result: List[Int] = for {
  incremented <- increment(splited)
} yield incremented

这将返回result: List[Int] = List(2)。无论您是否期望这是另一回事-我不确定您期望increment返回什么。

答案 1 :(得分:0)

请考虑以下示例,以了解理解的含义:

//For comprehension:
for {
    a <- aMonad
    b <- bMonad
    //....some more....
    z <- zMonad
} yield {
    ???
}

//means:
aMonad.flatMap { a =>
    bMonad.flatMap { b =>
        //{{{...some more
        //notice here it is .map instead of flatMap
        zMonad.map { z =>
            //something
            ???
        }
        //}}}
    }
}

单子aMonad,bMonad,.. zMonad应该是类似类型的单子,例如List [_],Future [_]等,以用于理解。

这意味着不能像上面的代码那样使用List [Int]类型的aMonad和Future [Int]类型的bMonad,但是如果它们属于List [Int]和List则没有问题[String]类型。

更多读数:

https://docs.scala-lang.org/tutorials/FAQ/yield.html

https://darrenjw.wordpress.com/2016/04/15/first-steps-with-monads-in-scala/