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

时间:2017-04-22 13:39:59

标签: scala function scala-cats

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

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

1 个答案:

答案 0 :(得分:1)

问题在于Scala类型推断的细节。它首先无法推断import requests with requests.Session() as s: headers1 = {'Cookie':'wordpress_test_cookie=WP Cookie check'} datas={'log':'admin','pwd':'admin','wp-submit':'Log In','redirect_to':'/wordpress/wp-admin/','testcookie':'1'} s.post("http://ip/wordpress/wp-admin",headers=headers1,data=datas) re = s.get("http://ip/wordpress/wp-admin").text print (re) ,然后从中推断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]) 的任何子类型!