【问题标题】:Scala type checker cannot infer types correctlyScala 类型检查器无法正确推断类型
【发布时间】:2015-11-01 07:13:18
【问题描述】:

我简化了 Scala 类型推断的问题:

  case class HalfEdg[N,E](e:E, n:N)
  case class Nod[N,E](head:N, edgs:HalfEdg[N,E])

  case class AA[E](e:E) {
    def ->[N](n:N):HalfEdg[N,E] = HalfEdg(e,n)
  }
  def --[E](e:E):AA[E] = AA(e)

我可以制作这个变量:

val x = Nod[Int,String](13, --("aa")->(12))

然后我想将它扩展到以下类型:

  case class Foo[N](e:N => Boolean)
  case class Bar[E](e:E => Boolean)

  case class BB[E](e:Bar[E]) {
    def ->[N](n:Foo[N]):HalfEdg[Foo[N],Bar[E]] = HalfEdg(e,n)
  }  
  def --?[E](e:E => Boolean):BB[E] = BB(Bar(e))

但这次我不能做同样的事情,因为编译器无法推断 Foo 和 Bar 中的函数类型:(我可以静态键入它们并编译)

  val x1 = Nod[Foo[Int],Bar[String]](Foo(x => x == 10), --?(x => x == "")->(Foo(z => z == 10)))

我该如何解决这个问题?

【问题讨论】:

    标签: scala types


    【解决方案1】:

    类型推断失败的中心是编译器无法确定Foo(z => z == 10) 中的N 类型与N 类型相同 N来自较早的Foo(x => x == 10)。一种可能的解决方法是确保Foo、Bar、BB 和--? 的定义都使用相同的N 和E。这可以通过将它们包装在使用N 和E 类型参数化的父(“上下文”)特征中来完成。例如:

    trait Baz[N,E] {
      case class Foo(e:N => Boolean)
      case class Bar(e:E => Boolean)
    
      case class BB(e:Bar) {
        def ->(n:Foo):HalfEdg[Foo,Bar] = HalfEdg(e,n)
      }
      def --?(e:E => Boolean):BB = BB(Bar(e))
    }
    

    从这里,您可以在特定上下文中执行所需的操作,作为 Baz 的一个版本,满足 N 和 E 的特定所需类型:

    object IntStrBaz extends Baz[Int,String] {
      // do your work in here
      val x1 = Nod[Foo,Bar](Foo(x => x == 10), --?(x => x == "")->(Foo(z => z == 10)))
    }
    

    粘贴到 REPL 中,我们不再收到类型推断投诉:

    scala> IntStrBaz.x1
    res0: Nod[IntStrBaz.Foo,IntStrBaz.Bar] = Nod(Foo(<function1>),HalfEdg(Bar(<funct
    ion1>),Foo(<function1>)))
    

    【讨论】:

      【解决方案2】:

      你所需要的只是简化你的表达,它会很容易地显示你的错误。 您错过了两个设置类型的地方:

        val bbE = --?[String](x => x == "")
        val foo = Foo(z => z == 10)
        val zz = bbE->(foo)
        val x1 = Nod[Foo[Int],Bar[String]](Foo(x => x == 10), zz)
      

      对于此类问题,如果您帮助编译器进行类型推断,则更容易识别问题。

      【讨论】:

      • 这不是为什么它不能推断类型的全部问题!在第二种情况下,它可以在第一个示例中做到!我知道,如果静态键入所有内容,它将起作用!
      • 您现在可以删除。问题在于调用函数--? 和Foo。你没有为他们正确设置type。
      • 看看你的--?函数。它接受x - 没有关于类型的信息。 scala 可以从中推断出什么类型?
      • 抱歉,我无法理解,请您改写有问题的结构,使其可行或不可行?如果是,请执行。如果不是,为什么它可以在Nod[Int,String](13, --("aa")-&gt;(12))
      • 试试val x1 = Nod[Foo[Int],Bar[String]](Foo(x =&gt; x == 10), --?[String](x =&gt; x == "")-&gt;(Foo(z =&gt; z == 10)))
      猜你喜欢
      • 1970-01-01
      • 2011-10-16
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多