Why does Scala type inference fail here?

后端 未结 1 1002
故里飘歌
故里飘歌 2021-02-08 03:25

I have this class in Scala:

object Util {
  class Tapper[A](tapMe: A) {
    def tap(f: A => Unit): A = {
      f(tapMe)
      tapMe
    }

    def tap(fs: (A          


        
1条回答
  •  误落风尘
    2021-02-08 03:55

    6.26.3 Overloading Resolution

    One first determines the set of functions that is potentially applicable based on the shape of the arguments

    ...

    If there is precisely one alternative in B, that alternative is chosen.

    Otherwise, let S1, . . . , Sm be the vector of types obtained by typing each argument with an undefined expected type.

    Both overloads of tap are potentially applicable (based on the 'shape' of the arguments, which accounts for the arity and type constructors FunctionN).

    So the typer proceeds as it would with:

    val x = _.trim
    

    and fails.

    A smarter algorithm could take the least upper bound of the corresponding parameter type of each alternative, and use this as the expected type. But this complexity isn't really worth it, IMO. Overloading has many corner cases, this is but another.

    But there is a trick you can use in this case, if you really need an overload that accepts a single parameter:

    object Util {
      class Tapper[A](tapMe: A) {
        def tap(f: A => Unit): A = {
          f(tapMe)
          tapMe
        }
    
        def tap(f0: A => Unit, f1: A => Unit, fs: (A => Unit)*): A = {
          (Seq(f0, f1) ++ fs).foreach(_(tapMe))
          tapMe
        }
      }
    
      implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap)
    
      "".tap(_.toString)
      "".tap(_.toString, _.toString)
      "".tap(_.toString, _.toString, _.toString)
    }
    

    0 讨论(0)
提交回复
热议问题