【问题标题】:How to aid Scala in type inference?如何帮助 Scala 进行类型推断?
【发布时间】:2016-03-12 18:18:11
【问题描述】:

有时 Scala 难以推断类型。这里的目标是了解原因并尝试帮助 Scala 进行更好的推理。

用一个简单的例子可以更好地解释这个问题:

trait A
trait B

class G[Ao <: A, Bo <: B](a: Ao, b: Bo)

// This is my "complex" class with 3 type parameters
class X[Ao <: A, Bo <: B, Go <: G[Ao,Bo]](a: Ao, b: Bo, g: Go)

val a  = new A{}
val b  = new B{}
val g  = new G(a,b)

下面的 OO 类型完美推断:

class OO extends X(a,b,g) // Type of X[A,B,G[A,B]]

但是,如果我们将其中一个参数更改为一个选项(或任何集合),并且我们提供一个空集合(或 None),那么推理将不起作用。

case class X[Ao <: A, Bo <: B, Go <: G[Ao,Bo]](a: Ao, b: List[Bo], g: Go)

class OO extends X(a,List(),g)

<console>:XX: error: inferred type arguments [A,Nothing,G[A,B]] do not conform to class X's type parameter bounds [Ao <: A,Bo <: B,Go <: G[Ao,Bo]]
       class OO extends X(a,List(),g)
                        ^
<console>:XX: error: type mismatch;
 found   : A
 required: Ao
       class OO extends X(a,List(),g)
                          ^
<console>:XX: error: type mismatch;
 found   : G[A,B]
 required: Go
       class OO extends X(a,List(),g)

这可以通过像这样显式传递 OO 的所有参数来解决:

class OO extends X[A,B,G[A,B]](a,List(),g)

问题是,G 已经有了它的类型,从 X 的定义中我们看到 G 接受了 X 的前两个参数,所以如果我们知道 G,我们就拥有了推断 X 的参数所需的一切。我可以做一些不同的事情来帮助 Scala 进行推理吗?我有一个类,它的参数比 X 多得多,现在我总是必须明确定义它们。我正在尝试查看是否可以做些什么来帮助 Scala 成功推断类型。

【问题讨论】:

    标签: scala type-inference


    【解决方案1】:

    我猜你可以使用更高种类的类型:

    case class X[Ao <: A, Bo <: B, Go[GAo <: Ao, GBo <: Bo] <: G[GAo, GBo]](a: Ao, b: List[Bo], g: Go[Ao, Bo])
    class OO extends X(a,List(),g)
    

    或者,如果您的类型参数是协变的:

    case class G[+Ao <: A, +Bo <: B](a: Ao, b: Bo)
    case class X[Ao <: A, Bo <: B, Go[_ <: Ao, _ <: Bo] <: G[Ao, Bo]](a: Ao, b: List[Bo], g: Go[Ao, Bo])
    

    我从经验中知道,当 scala 编译器在“不同级别”上相互依赖时,无法从同一组的参数推断类型,就像在这个例子中一样。更高种类的类型允许我显式声明类型边界并帮助编译器推断正确的类型。

    【讨论】:

    • 这看起来很有希望!让我检查一下,我会回复你的。
    • 你能解释一下你的推理吗?是什么让你想到了更高尚的人?
    • 我在答案中添加了(某种)解释。我想在类型系统和函数式编程方面更有经验的人可以解释为什么它比我工作得更好。我只从经验中知道编译器在这些情况下无法推断类型参数,您必须像我一样通过指定边界来“帮助”它。对不起,我帮不上忙:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 2020-04-29
    • 2012-11-29
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多