在scala

时间:2016-08-15 09:14:10

标签: scala function

我试图了解隐含参数的来源。以下是泛型类型约束隐式解析的简单演示:

class ImplicitTypeConstraint[+T](val t : T) {
    def doSome1(implicit ev: T <:< Int) = println("Int value = " + ev(t))
    def doSome2(implicit ev: T <:< Int, u : Unit) = println("Int value = " + ev(t))
    def doSome3(u : Unit)(implicit ev: T <:< Int) = println("Int value = " + ev(t))
}

现在我尝试了这个

val itc = new ImplicitTypeConstraint(10)
itc.doSome1    //compiles fine
itc.doSome1()  //compile error, Cannot resolve reference doSome1 with such signature

itc.doSome2    //compile error, not enough arguments for method doSome2
itc.doSome2()  //compile error, Cannot resolve reference doSome2 with such signature

itc.doSome3    //compile error, Cannot resolve reference doSome3 with such signature
itc.doSome3()  //compiles fine

问题是,doSome1doSome2的签名之间有什么区别?我来自Java,我想,foo()将调用一个没有 显式 参数的函数,但它似乎找到一个带有一个参数的函数类型为Unit

UPD :在我明确构建项目之前,Itellij没有显示错误。 doSome2()doSome2都拒绝编译。

2 个答案:

答案 0 :(得分:2)

f()调用一个带有空参数列表的方法(可能在此列表后面带有隐式参数)。 doSome1doSome2都没有空参数列表,因此itc.doSome1()itc.doSome2()无法编译。 itc.doSome编译,因为它调用没有参数列表的函数,并插入隐式参数。 itc.doSome2无法编译,因为范围内没有implicit Unit

itc.doSome3()中,()是类型Unit的值,而不是方法调用括号。所以它实际上是itc.doSome3(())。编译器应该发出警告:

Warning:(15, 13) Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want.
        signature: ImplicitTypeConstraint.doSome3(u: Unit)(implicit ev: <:<[T,Int]): Unit
  given arguments: <none>
 after adaptation: ImplicitTypeConstraint.doSome3((): Unit)
itc.doSome3();//
           ^

答案 1 :(得分:1)

我认为重点是,需要在隐式范围内将{strong>类型视为Int。你可以自己提供

implicit val intView = implicitly[Int <:< Int]

val itc = new ImplicitTypeConstraint(10)
itc.doSome1

然后您可以按如下方式定义doSome1

class ImplicitTypeConstraint[+T](val t : T) {
    def doSome1()(implicit ev: T <:< Int) = println("Int value = " + ev(t))
    def doSome2(implicit ev: T <:< Int, u : Unit) = println("Int value = " + ev(t))
    def doSome3(u : Unit)(implicit ev: T <:< Int) = println("Int value = " + ev(t))
}

然后两个:

itc.doSome1    //compiles fine
itc.doSome1()  // compiles fine too

但要致电doSome2

itc.doSome2()                 //compiles fine
itc.doSome2(intView, println) // implicit won't work here

致电doSome3。这是在方法中使用含义的通常/正确方法。你最好curry就是这样。

itc.doSome3(println) // compiles fine