Scala 类型推断不适用于类型边界,除非明确指定类型

Scala type inference does not work with type bounds, unless the type is specified explicitly

我正在尝试围绕 Scala 中的函数创建一个文档包装器,以便可以查询包装器以获取其包含函数的文档,如下所示:

trait WrappedFunction1[A, B] {
  def f : Function1[A, B]
  def doc: String
  def apply(x:A):B = f(x)
  def compose[C, T <:WrappedFunction1[B, C]](that:T):WrappedFunction1[A, C] = 
    new Wrapper[A, C](this.f andThen that.f, this.doc + " composed with " + that.doc)
}

class Wrapper[A, B](f1:Function1[A, B], sos:String) extends WrappedFunction1[A, B] {
  val f = f1
  val doc = sos
}

object Wrapper {
  implicit class Wrap[A, B](f1:Function1[A, B]) {
    def wrap(sos:String):WrappedFunction1[A, B] = new Wrapper(f1, sos)
  }
}

以下是我的使用方法:

import Wrapper._
val x : String => String = _.toLowerCase
val y : String => String = _.toUpperCase
val x1 = x.wrap("a function for lowercasing")
val y1 = y.wrap("a function for uppercasing")

println(x1("LOL")) // lol
println(x1.doc) // a function for lowercasing

但是,当我编写其中两个时,无法推断出类型:

val xy = x1 compose y1

cmd3.sc:1: inferred type arguments [Nothing,cmd3Wrapper.this.cmd1.cmd0.wrapper.WrappedFunction1[String,String]] do not conform to method compose's type parameter bounds [C,T <: cmd3Wrapper.this.cmd1.cmd0.wrapper.WrappedFunction1[String,C]]
val xy = x1 compose y1
            ^cmd3.sc:1: type mismatch;
 found   : cmd3Wrapper.this.cmd1.cmd0.wrapper.WrappedFunction1[String,String]
 required: T
val xy = x1 compose y1
                    ^
Compilation Failed

如果我明确说明类型,则可以组合它们:

val xy = x1 compose[String, WrappedFunction1[String, String]] y1

我哪里出错了吗? 还有更好的方法吗? (我尝试了类型类,但它们似乎是为具有一种类型参数的特征定义的,也许是任何其他代数数据类型?)

问题出在 Scala 类型推断的细节上。它不能先推断出T,然后从中推断出C;相反,它必须同时推断出两者。

that: T可以确定T,但是C在参数类型中没有提到,所以它被赋值Nothing并且只有在下一步编译器注意到它不合适。所以解决方法是将类型更改为

def compose[C, T <:WrappedFunction1[B, C]](that: T with WrappedFunction1[B, C])

或者更好,只是

def compose[C](that: WrappedFunction1[B, C])

因为这已经允许传递 WrappedFunction1[B, C]!

的任何子类型