Scala中

时间:2016-11-17 14:16:31

标签: scala functional-programming pattern-matching anonymous-function type-inference

我是一名初学者Scala开发人员,他在编写练习时遇到了问题(5.12),这本书采用了#34; Scala中的函数编程"保罗丘萨诺。

我在这里有一个名为展开的函数,它接受一个初始状态和一个生成具有下一个状态的流的函数:

def unfold[A,S](z: S)(f: S => Option[(A,S)]): Stream[A] = f(z) match {
  case Some((h,t)) => h #:: unfold(t)(f)
  case _ => Stream.empty
} 

例如,使用此功能可以创建无限的对象流,例如

def constant[A](a: A): Stream[A] = unfold(a)(_ => Some(a,a))

现在,我想创建Fibonacci序列,然后输入:

def fibs: Stream[Int] = unfold((0,1))((a,b) => Some(a,(b,a+b)))

我收到这些错误:

  • 缺少参数类型b

  • Some [((Int,Int),(Nothing,String))]类型的表达式不符合预期类型Option [(A _,(Int,Int))]

如果我在传递给展开的匿名函数中使用 case 关键字,例如:

{ case (a,b) => Some(a,(b,a+b))}

一切都很好。

所以我的问题是:两个实现之间的区别是什么?是不是我不理解的类型推断?

2 个答案:

答案 0 :(得分:2)

MAX()

是一个带有两个参数的函数 - { (a,b) => Some(a, (b, a+b)) } a,并返回一个选项(元组的)。这不是你需要的。您想要定义一个带有单个(元组)参数的函数。一种方法是这样的:

b

您可以扩展为以下内容:

 { tuple => Some(tuple._1, (tuple._2, tuple._1 + tuple._2)) }

这看起来很长,但是scala有一个特殊的语法结构,它允许你使用类似于模式匹配的语法(动态地“解析 { tuple => val a = tuple._1 val b = tuple._2 // Can also do it shorter, with automatic unapply here: // val (a,b) = tuple // this is already pretty similar to what you have with `case`, right? Some(a, (b, a+b)) } ,在运行时将复杂参数解构为匿名函数,同样如模式匹配那样):

unapply

这与上面完全相同。

答案 1 :(得分:0)

您似乎已经达成了有关编译器如何解释代码的规则之一:

A normal function of one arg:

scala> val g = (x: Int) => x + 1
g: Int => Int = <function1>

The data type for a tuple of ints is Tuple2(Int, Int):
scala> (3,4)
res3: (Int, Int) = (3,4)

scala> val a: Tuple2[Int, Int] = (3,4)
a: (Int, Int) = (3,4)

But this does not work:

scala> val f = ((a,b): (Int, Int)) => a+b
<console>:1: error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
      Either create a single parameter accepting the Tuple1,
      or consider a pattern matching anonymous function: `{ case (param1, param1) => ... }
val f = ((a,b): (Int, Int)) => a+b
              ^
This works:
scala> val f = (x: Tuple2[Int, Int]) => x._1 + x._2
f: ((Int, Int)) => Int = <function1>

这是你认为你可以做的:

val f = ((a, b): (Int, Int)) => Some(a, (b, a + b))

然后(在unfold的上下文中)(0,1)被理解为类型(Int, Int),所以当你调用unfold时你可以省略类型声明并且只写((a, b)) => Some(a, (b, a + b))。但它不起作用,因为“元组不能在方法或函数参数中直接解构”。 上面的函数f甚至不能在unfold之外编译。相反,这编译: val g = (x: Tuple2[Int, Int]) => Some(x._1, (x._2, x._1 + x._2))