除非明确指定类型,否则Scala Type推断不与类型界限起来



我正在尝试创建围绕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

我出错了吗?还有一个更好的方法吗?(我尝试了类型类,但似乎是针对具有一种类型param的特征定义的,也许是其他代数数据类型?(

问题在于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]的任何子类型!

相关内容

最新更新