Scala 2.8的一个新功能是上下文边界.什么是上下文绑定以及它在哪里有用?
当然我先搜索(例如找到这个),但我找不到任何非常清晰和详细的信息.
我有一些像这样的代码:
class ReflectiveJsonFormat[T:TypeTag] extends JsonFormat[T] {
def write(x: T) : JsValue = {
val t = typeOf[T]
val getters = t.declarations.filter { s => s.isMethod && s.asMethod.isGetter }
val mirror = runtimeMirror(this.getClass.getClassLoader)
val instanceMiror = mirror.reflect(x)
}
}
Run Code Online (Sandbox Code Playgroud)
最后一行失败了:
没有ClassTag可用于T
我以为TypeTag是比一个更多的信息ClassTag?我能得到ClassTag从TypeTag?如果没有,是否有一些语法可以说T有两个上下文边界 - 两个TypeTag和ClassTag?或者,您将如何修复此代码?
注意:我正在提出这个问题来自己回答,但欢迎其他答案.
请考虑以下简单方法:
def add[T](x: T, y: T)(implicit num: Numeric[T]) = num.plus(x,y)
Run Code Online (Sandbox Code Playgroud)
我可以使用如下的上下文绑定重写它
def add[T: Numeric](x: T, y: T) = ??.plus(x,y)
Run Code Online (Sandbox Code Playgroud)
但是如何获取该Numeric[T]类型的实例以便我可以调用该plus方法?
是否可以使用更高kinded类型的上下文边界语法快捷方式?
trait One { def test[W : ClassManifest]: Unit } // first-order ok
trait Two { def test[W[_]: ClassManifest]: Unit } // not possible??
trait Six { def test[W[_]](implicit m: ClassManifest[W[_]]): Unit } // hmm...
Run Code Online (Sandbox Code Playgroud) 在scala-arm项目中,我看到这样的代码:
def managed[A : Resource : Manifest](opener : => A) : ManagedResource[A] = new DefaultManagedResource(opener)
Run Code Online (Sandbox Code Playgroud)
有人可以解释[A:资源:清单]的含义吗?
在我的库中,我有三个类型类:
trait Monoid[T] {
val zero : T
def sum(x : T, y : T) : T
}
trait AbelianGroup[T] extends Monoid[T] {
def inverse(x : T) : T
def difference(x : T, y : T) : T
}
//represents types that are represents lists with a fixed number of elements, such as
//the tuple type (Int, Int)
trait Vector[T, U] {
...
}
Run Code Online (Sandbox Code Playgroud)
在以下条件下,这些类型类可以相互转换:
T是一个scala.math.Numeric类型,它也是一个类型AbelianGroup.T是a AbelianGroup,那么它也是一个Monoid(当前AbelianGroup …def bar[T: Manifest](a: Array[T]) = Array.ofDim[T](3)
class Foo
bar(Array(new Foo)) //Array[Foo] = Array(null, null, null)
Run Code Online (Sandbox Code Playgroud)
如上所示,清单似乎隐含地存在于任意类型中.
由于我们有一个上下文绑定,这意味着会有一些类型没有隐式Manifest - 它们是什么?
当我尝试向我的case类添加宏注释时:
@macid case class CC[A: T](val x: A)
Run Code Online (Sandbox Code Playgroud)
我收到错误:
private[this] not allowed for case class parameters
Run Code Online (Sandbox Code Playgroud)
@macid 只是身份函数,定义为whitebox StaticAnnotation:
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
import scala.annotation.StaticAnnotation
class macid extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro macidMacro.impl
}
object macidMacro {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
new Macros[c.type](c).macidMacroImpl(annottees.toList)
}
}
class Macros[C <: Context](val c: C) {
import c.universe._
def macidMacroImpl(annottees: List[c.Expr[Any]]): c.Expr[Any] =
annottees(0)
}
Run Code Online (Sandbox Code Playgroud)
未注释的代码有效:
case class CC[A: T](val x: A)
Run Code Online (Sandbox Code Playgroud)
如果我删除上下文绑定它是有效的:
@macid case class CC[A](val …Run Code Online (Sandbox Code Playgroud) 我正在使用以下用Scala 2.11.8编写的代码:
sealed trait Acceptable[T]
object Acceptable {
implicit object Int extends Acceptable[Int]
implicit object String extends Acceptable[String]
}
case class Enc[T](f: T => Any)
implicit def test[I, T](implicit f: I => T, a: Acceptable[T]): Enc[I] =
Enc[I](f)
val e = implicitly[Enc[Int]]
Run Code Online (Sandbox Code Playgroud)
它成功编译.
如您所见,a: Acceptable[T]参数应该很容易转换为上下文绑定:
implicit def test[I, T: Acceptable](implicit f: I => T): Enc[I] =
Enc[I](f)
Run Code Online (Sandbox Code Playgroud)
但在那之后,更改编译开始失败并出现错误:
找不到参数e的隐含值:app.Enc [Int]
为什么会这样?
更新:
我试过-Xlog-implicits编译选项和编译日志给我:
[info] /path/to/ScalaTest/src/main/scala/app/Main.scala:60: test is not a valid implicit value for app.Enc[Int] …Run Code Online (Sandbox Code Playgroud) context-bound ×10
scala ×10
implicit ×2
typeclass ×2
arrays ×1
case-class ×1
manifest ×1
reflection ×1
scala-2.10 ×1
scala-2.8 ×1
scala-macros ×1
view-bound ×1