【发布时间】:2020-08-26 03:43:57
【问题描述】:
我正在关注 Paul Chiusano 和 Rúnar Bjarnason 的出色 Functional Programming in Scala,并且对我发现的奇怪/意外行为提出了疑问。
我已经像这样定义了一个foldRight 函数
def foldRight[A,B](l: List[A], z: B)(f: (A,B) => B): B =
l match {
case Nil => z
case x :: xs => f(x, foldRight(xs, z)(f))
}
只要我传入具体的参数,它就可以正常工作,例如:
foldRight((1 to 10).toList, 0)(_ + _)
val res6: Int = 55
如果我定义一个采用通用列表的类似函数
def sum[A](as: List[A]): Int = foldRight(as, 0)(_ + _)
奇怪的事情发生了
def sum[A](as: List[A]): Int = foldRight(as, 0)(_ + _)
^
fold.scala:23: error: type mismatch;
found : Int
required: String
最初,我对这个错误消息感到非常困惑,因为唯一的类型是A、B 和Int。然而,它似乎只是试图通过调用.toString 来理解+ 和通用A,就像我read about here 一样。
如果是这样的话,为什么不简单地添加 a1.toString + a2.toString + ... + a n.toString + 0 = something0?编译器完全理解 Scala 中 String 和 Int 之间的字符串连接。
希望有人可以帮助澄清这里发生的事情。
【问题讨论】:
-
您希望如何汇总通用
A的列表?如果我给您 Users 的 Maps 的 List 怎么办?这应该让你知道什么是错的。现在,对于特定的错误消息(_ + _)扩展为(x: A, y: Int) => x + y,因为我们不知道 A 的任何内容,所以我们可以假设它具有与 Any 相同的方法b>,它确实有一个+方法(由于该死的Java),它也接受一个Any并返回一个String。所以x + y给出了一个String,但编译器期望来自(A, Int) => Int的函数,因此出现错误。 -
此时,您根本无法编写该函数。稍后,您将了解 typclasses,并且您将能够根据表现为 Number 的任何 A 来编写此函数。跨度>
-
超级有用和明确的答案,谢谢你,路易斯!
-
查看scala-lang.org/api/current/scala/Any.html并通过继承过滤成员以找到
+方法 -
@Saskia 从技术上讲没有。实际上是的,因为任何东西都必须具有 Any 的所有方法(但它们可能会抛出异常,例如
null,或者您可能永远无法获得调用方法的实际值,就像 Nothing)。另外,我相信从 A 到 Any 的隐式转换总是在范围内。
标签: scala generics functional-programming fold