【问题标题】:Scala Polymorphic Function That Would Compile But Would Not Run As Expected可以编译但不会按预期运行的 Scala 多态函数
【发布时间】:2017-06-05 16:09:19
【问题描述】:

鉴于以下两个 Scala 函数,都按预期编译。

scala> def toList[A](a: A) = List(a)
toList: [A](a: A)List[A]

scala> def foo[A](f: A => List[A], b: A) = f(b)
foo: [A](f: A => List[A], b: A)List[A]

然而,当你运行它时,它给出了以下错误消息:

scala> foo(toList, 12)
<console>:14: error: type mismatch;
 found   : Nothing => List[Nothing]
 required: Int => List[Int]
       foo(toList, 12)

为什么 Scala 认为 toList 函数是 Nothing =&gt; List[Nothing] 而不是 Int =&gt; List[Int]

【问题讨论】:

  • 在这种情况下,推理引擎需要一点帮助:foo[Int](toList, 34)foo(toList[Int], 34)

标签: scala parametric-polymorphism


【解决方案1】:

根据foo 的定义方式,foo(12, toList) 传递参数是错误的。正确的方式是foo(toList, 12)

为什么 Scala 认为 toList 函数是 Nothing => List[Nothing] 而不是 Int => List[Int]?

12Int 类型,因为 foo

def foo[A](f: A => List[A], b: A) = f(b)

对于 toList 函数,它也期望 A 类型为 Int

如果您将foo 称为foo(toList, 12D),我们会收到以下错误

<console>:22: error: type mismatch;
 found   : Nothing => List[Nothing]
 required: Double => List[Double]
       foo(toList, 12D)

因为12DDouble type,而toList 也应该是Double

所以正确的方法是

foo(toList[Any], 12)

【讨论】:

    【解决方案2】:

    Scala 编译器将尝试推断方法的类型参数,它会查看定义在第一个括号中的参数并尝试从中提取类型,如果不能,它将选择下一个参数组来推断类型等等...

    定义该函数的最佳方式是这样

    def foo[A](b: A)(f: A => List[A]) = f(b)
    

    按此顺序提供参数将使您无需向编译器提供一些提示。你可以这样调用这个函数:

    foo(2.0d)(toList)
    

    你会得到一个 List[Double]

    如果你保持其他顺序,你需要给编译器一个提示,以便找出类型参数 A

    foo(toList[Double], 2.0d)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-17
      • 1970-01-01
      • 2020-06-02
      • 1970-01-01
      相关资源
      最近更新 更多