【问题标题】:Getting Scala type bound error: not found: type <%<获取 Scala 类型绑定错误:未找到:类型 <%<
【发布时间】:2013-02-20 15:31:55
【问题描述】:

所以我一直在尝试通过twitter Scala school 学习 Scala。但我目前被困在他们的type bound examples 之一。

特别是,它是使用&lt;%&lt; 类型关系运算符将类型绑定为特定类型的类型。

当我在 Scala 控制台中执行以下代码时:

scala> class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value }

...我收到以下错误:

<console>:7: error: not found: type <%<
       class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value }
                                                                     ^
<console>:7: error: overloaded method value + with alternatives:
  (x: Double)Double <and>
  (x: Float)Float <and>
  (x: Long)Long <and>
  (x: Int)Int <and>
  (x: Char)Int <and>
  (x: Short)Int <and>
  (x: Byte)Int <and>
  (x: String)String
 cannot be applied to (A)
       class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value }

我的问题是,为什么 Scala 解释器会抱怨?

我一直在尝试浏览 Scala 文档,但我无法在任何地方找到该操作员的信息。我可以看到 Scala 学校是在 Scala 2.8.0 的基础上创建的,而我正在运行 Scala 2.10.0 - 所以也许这已经被删除了?如果是这样,为什么这看起来像是一个有用的运算符?

【问题讨论】:

标签: scala type-bounds


【解决方案1】:

Scala 2.8 中的约束A &lt;%&lt; B 定义为

  sealed abstract class <%<[-From, +To] extends (From => To)
  object <%< {
    implicit def conformsOrViewsAs[A <% B, B]: A <%< B = new (A <%< B) {def apply(x: A) = x}
  }

所以你总是可以把它带回来。但是,我猜测它被弃用的原因是视图绑定只是要求从AB 的隐式函数,并且已经有一种非常好的方法可以以通用的方式表达该特定约束:

class Container[A](value: A) { def addIt(implicit evidence: A => Int) = 123 + value }

顺便说一句,值得注意的是,它不是运算符,而是中缀位置的类,从定义中可以看出。 =&gt; 也是如此,这只是引用 Function1 类型构造函数的另一种方式。

【讨论】:

  • 我一直在寻找有关删除课程的官方理由,但没有任何运气。你的猜测和任何人的猜测一样好,足以满足我的好奇心,谢谢! :)
【解决方案2】:

this site 上,它表示 A &lt;%&lt; B 在 Scala 2.9 中已被弃用。我不知道为什么,我同意这似乎有点奇怪,因为在我看来它也是一个非常有用的运算符。

【讨论】:

【解决方案3】:

正确的用法好像是

class Container[A](value: A) { def addIt[A <% Int] = 123 + value }

对于重载的值,scala 选择不解决歧义;在这种情况下,您必须做出决定。

  • 您可以尝试调试:-Xprint:typer

  • 或者您可以通过使用class Container[A](value: A) { def addIt = 123 + value.asInstanceOf[Int] } 或已经建议的class Container[A](value: A) { def addIt(implicit evidence: A =&gt; Int) = 123 + value } 来确定@​​987654324@ 确实是Int。它们是等价的。但是在这里你说AInt 的一种;与A 相反,可以将Int 视为&lt;% 所做的。

第二个选项不是微不足道的。考虑以下

scala> class Container[A](value: A) { def printIt[A <% Int] = println( 123+" could be " + value) }
defined class Container

scala> val x = new Container("Love")
x: Container[String] = Container@21ebfd82

scala> x.printIt
123 could be Love

显然"love" 不是Int 的类型,因为它是String,但在这种情况下它完全没问题:这就是为什么你应该小心使用A =&gt; Int

【讨论】:

  • 顶部的sn-p绝对不是正确的用法! 'addIt' 方法上的类型参数 A 隐藏了类上的参数 A,因此不会在这种情况下添加任何内容。
  • 您的第二个示例仅因为全局隐式 any2stringAdd 而起作用,它允许将任何类型转换为字符串以进行连接 - 这完全与这个问题有关。另外,不能说{ def addIt = 123 + value.asInstanceOf[Int] }{ def addIt(implicit evidence: A =&gt; Int) = 123 + value } 是等价的。一个是不安全的强制转换,对于任何不是 Int 子类型的东西,它都会在编译时爆炸。另一种是类型安全的,依赖于范围内的隐式转换。
  • 抱歉,在运行时炸毁,而不是编译时。
猜你喜欢
  • 2021-08-11
  • 1970-01-01
  • 2016-08-09
  • 1970-01-01
  • 2021-06-07
  • 2019-05-08
  • 1970-01-01
  • 2011-08-26
  • 1970-01-01
相关资源
最近更新 更多