scalaimplicitscala-3

Can't execute an extension method of a context function in Scala 3


I defined an extension method on a context function in Scala 3:

object Scope {
  extension [E, A](a: List[E] ?=> A) def extFoo: A = foo(a)
  
  private def foo[E, A](a: List[E] ?=> A) = {
    given s: List[E] = List.empty
    println(a)
    a
  }
}

However, when I try to use it, the compiler complains. The following @main:

@main def main(): Unit = {
  val i: List[String] ?=> Int = 1
  import Scope.extFoo
  i.extFoo
}

generates this error:

No given instance of type List[String] was found for parameter of (List[String]) ?=> Int
  i.extFoo

Everything works fine if I call the extension method with the alternative syntax, extFoo(i).

Is it the expected behavior?


Solution

  • In i.extFoo what doesn't compile is i itself. i looks for an implicit List[String] in the scope and doesn't find such implicit.

    This is consistent with docs

    given ec: ExecutionContext = ...
    
    def f(x: Int): ExecutionContext ?=> Int = ...
    
    f(2)(using ec)   // explicit argument
    f(2)             // argument is inferred
    

    https://docs.scala-lang.org/scala3/reference/contextual/context-functions.html

    .extFoo is tried to be applied to the result of such application, not to the original implicit function.

    ....extFoo can be resolved or not depending on existence of extension method in the scope but .extFoo can't fix compilation of ....

    https://scala-lang.org/files/archive/spec/3.4/07-implicits.html#views

    If you mean that .extFoo should be applied to the original implicit function then you can specify this with implicit lambda

    val i: List[String] ?=> Int = 1
    import Scope.extFoo
    ((_: List[String]) ?=> i).extFoo // compiles