2013-02-20 121 views
7

所以我一直试图通过twitter Scala school来学习Scala。但我目前卡在type bound examples之一。获取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 2.8.0创建的,而且我正在运行Scala 2.10.0 - 所以也许这已被删除?如果是这种情况,为什么这看起来像一个有用的操作符?

+2

看起来这是不是在Scala 2.10,但我不确定为什么 - https://github.com/scala/scala/blob/v2.10.0/src/library/scala/Predef.scala #L1 – Impredicative 2013-02-20 15:37:58

+4

已在https://github.com/scala/scala/commit/e1780e9686914d835b295e125511368eeb1d0733#L0L350 – Debilski 2013-02-20 16:38:37

+1

中弃用!看起来正是我在下面猜测的原因。 – Impredicative 2013-02-20 16:58:11

回答

6

约束A <%< B斯卡拉2.8定义为

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 } 

顺便说一下,值得注意的是,从定义中可以看出,它不是一个运算符,而是一个处于中缀位置的类。 =>也是如此,这是参考Function1类型构造函数的另一种方式。

+1

我一直在寻找官方推理背后的班级,但没有任何运气。你的猜测和任何人一样好,足以满足我的好奇心,谢谢! :) – jpihl 2013-02-20 16:30:44

2

this site,它表示A <%< B在Scala 2.9中已弃用。我不知道为什么,我同意这看起来有点奇怪,因为它对我来说也是一个非常有用的操作符。

+2

正如在https://github.com/scala/scala/commit/e1780e9686914d835b295e125511368eeb1d0733#L0L350上的GitHub变更中所描述的那样,由于A <> 2013-02-20 17:50:23

-1

正确的用法似乎是

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

至于重载值,scala是选择不解决不确定性;在这种情况下,你必须做出决定。

  • 你可以尝试用调试:-Xprint:typer

  • ,或者你可以决定A确实Int使用class Container[A](value: A) { def addIt = 123 + value.asInstanceOf[Int] }或已经建议class Container[A](value: A) { def addIt(implicit evidence: A => Int) = 123 + value }无论是。它们是等价的。但是在这里你是说A是一种Int;而不是A可以看作Int这就是<%所做的。

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

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] = [email protected] 

scala> x.printIt 
123 could be Love 

显然"love"不是一个类型的Int因为它是String,但它在这方面的完美的罚款:这就是为什么你应该小心使用A => Int

+0

顶部的代码段绝对不是正确的用法! 'addIt'方法的类型参数'A'在类上映射参数'A',所以没有增加这种情况。 – Impredicative 2013-02-20 17:08:25

+0

你的第二个例子仅仅是因为一个全局隐式的'any2stringAdd',它可以让任何类型转换为一个字符串来连接它 - 这完全是偶然的。另外,说'+ def addIt = 123 + value.asInstanceOf [Int]}'和'{def addIt(隐式证据:A => Int)= 123 + value}'是等价的。一种是不安全的演员,在编译时会炸毁任何不是Int的子类型的东西。另一种是类型安全的,依赖于范围内的隐式转换。 – Impredicative 2013-02-20 17:13:08

+0

对不起,在运行时炸掉了,不是编译时间。 – Impredicative 2013-02-21 09:06:46

相关问题