gpt4 book ai didi

scala - 错误 : polymorphic expression with default arguments

转载 作者:行者123 更新时间:2023-12-04 08:27:23 25 4
gpt4 key购买 nike

以下是我的错误:

trait Foo[A]
class Bar[A](set: Set[Foo[A]] = Set.empty)

这产生
<console>:8: error: polymorphic expression cannot be instantiated to expected type;
found : [A]scala.collection.immutable.Set[A]
required: Set[Foo[?]]
class Bar[A](set: Set[Foo[A]] = Set.empty)
^

很烦我要在 Set.empty中重复type参数.为什么使用此默认参数进行类型推断会失败?以下工作:
class Bar[A](set: Set[Foo[A]] = { Set.empty: Set[Foo[A]] })

请注意,这与 Set 无关。特别是:
case class Hallo[A]()
class Bar[A](hallo: Hallo[A] = Hallo.apply) // nope

奇怪的是,这不仅有效:
class Bar[A](hallo: Hallo[A] = Hallo.apply[A])

...但还有这个:
class Bar[A](hallo: Hallo[A] = Hallo())      // ???

最佳答案

可以直接在empty上指定类型方法而不必添加额外的括号/大括号和类型注释:

class Bar[A]( set: Set[Foo[A]] = Set.empty[Foo[A]] )

至于为什么类型推断失败,看这些问题:
  • Type inference on Set failing?
  • missing parameter type error by calling toSet

  • 更新:

    我很抱歉,我的仓促回答太离谱了。上面帖子中的问题与此问题无关。 @TravisBrown 在他上面的评论中提出了一个很好的观点。起初这似乎有效:
    class Bar[A]( set: Set[A] = Set.empty )

    但是如果你真的尝试调用构造函数,它会在使用站点失败:
    new Bar[Int]
    // <console>:9: error: type mismatch;
    // found : scala.collection.immutable.Set[Nothing]
    // required: Set[Int]
    // Note: Nothing <: Int, but trait Set is invariant in type A.
    // You may wish to investigate a wildcard type such as `_ <: Int`. (SLS 3.2.10)
    // Error occurred in an application involving default arguments.
    // new Bar[Int]

    这表明编译器不会强制默认参数对所有 A 都有效。 , 只是为了一些 A .他们可能做出了这样的选择,因此您可以执行以下操作:
    scala> case class MyClass[T](set: Set[T] = Set(0))
    defined class MyClass

    scala> MyClass() // defaults to MyClass[Int]
    res0: MyClass[Int] = MyClass(Set(0))

    scala> MyClass(Set('x)) // but I can still use other types manually
    res1: MyClass[Symbol] = MyClass(Set('x))

    但是,任何带有参数化类型的嵌套都无法在构造函数的声明位置进行类型检查:
    class Bar[A]( set: Set[Option[A]] = Set.empty )
    // <console>:7: error: polymorphic expression cannot be instantiated to expected type;
    // found : [A]scala.collection.immutable.Set[A]
    // required: Set[Option[?]]
    // class Bar[A]( set: Set[Option[A]] = Set.empty )

    如果类型参数处于协变位置,则推理不会失败:
    class Bar[ A ]( set: List[Foo[A]] = List.empty ) // OK

    class Bar[ A ]( set: Map[Int,Foo[A]] = Map.empty ) // OK (unless you use it)

    class Bar[ A ]( set: Map[Foo[A],Int] = Map.empty ) // BAD
    // <console>:8: error: polymorphic expression cannot be instantiated to expected type;
    // found : [A, B]scala.collection.immutable.Map[A,B]
    // required: Map[Foo[?],Int]
    // class Bar[ A ]( set: Map[Foo[A],Int] = Map.empty ) // BAD
    // ^

    这些是有效的,因为编译器选择 Nothing默认为协变类型。这适用于 List ,但是如果您真的尝试调用它,则上面的第二个示例不起作用。

    大多数这种奇怪的原因可能是 Scala 处理默认参数的方式。编译器会自动向伴生对象添加一个额外的方法,然后无论您在何处遗漏参数,编译器都会自动向伴生对象中的新方法添加一个方法调用,以生成缺少的参数。看起来将默认参数抽象到一个方法中会破坏类型推断中的一些事情,这些事情可以与正常分配一起使用。

    我认为这些发现中的大多数都非常令人困惑。我从中得出的结论是,实际测试您的默认参数以确保它们在您尝试使用它们时不会破坏类型正确性非常重要!

    关于scala - 错误 : polymorphic expression with default arguments,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13109643/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com