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]
!
的任何子类型
我正在尝试围绕 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]
!