gpt4 book ai didi

Scala:错误:缺少参数类型

转载 作者:行者123 更新时间:2023-12-05 00:35:43 25 4
gpt4 key购买 nike

我正在尝试编写一些库函数来增强基本集合。大部分进展顺利,但我遇到了这个问题。

class EnhancedGenTraversableLike[A, Repr <: GenTraversable[A]](self: GenTraversableLike[A, Repr]) {
def mapValuesStrict[T, U, R, That](f: U => R)(implicit ev: A <:< (T, U), bf: CanBuildFrom[Repr, (T, R), That]) = {
val b = bf(self.asInstanceOf[Repr])
b.sizeHint(self.size)
for ((k: T, v: U) <- self) b += k -> f(v)
b.result
}
}
implicit def enhanceGenTraversableLike[A, Repr <: GenTraversable[A]](self: GenTraversableLike[A, Repr]) = new EnhancedGenTraversableLike[A, Repr](self)

这是我使用它时发生的情况:
scala> List((1,2),(2,3),(3,4),(2,5)).mapValuesStrict((_:Int).toString)
res0: List[(Int, java.lang.String)] = List((1,2), (2,3), (3,4), (2,5))

scala> List((1,2),(2,3),(3,4),(2,5)).mapValuesStrict(x => x.toString)
<console>:13: error: missing parameter type
List((1,2),(2,3),(3,4),(2,5)).mapValuesStrict(x => x.toString)
^

所以Scala无法确定 x的类型.

This answer表明 Scala 不使用一个参数来解析另一个参数,但单独的参数列表可以解决问题。然而,就我而言,这并不容易,因为类型信息是在隐式参数中找到的。

有没有办法解决这个问题,这样我就不必每次调用该方法时都指定类型?

更新:根据 Owen 的建议,我最终创建了一个特定于可遍历对的丰富类:
class EnrichedPairGenTraversableLike[T, U, Repr <: GenTraversable[(T, U)]](self: GenTraversableLike[(T, U), Repr]) {
def mapValuesStrict[R, That](f: U => R)(implicit bf: CanBuildFrom[Repr, (T, R), That]) = {
val b = bf(self.asInstanceOf[Repr])
b.sizeHint(self.size)
for ((k: T, v: U) <- self) b += k -> f(v)
b.result
}
}
implicit def enrichPairGenTraversableLike[T, U, Repr <: GenTraversable[(T, U)]](self: GenTraversableLike[(T, U), Repr]) = new EnrichedPairGenTraversableLike(self)

最佳答案

就在这里。让我举一个更简单的例子。我希望这也适用
你更复杂的用例。

说我们有

trait Foo[A]

class Bar {
def methWithImplicits[A,B](f: A => B)(implicit foo: Foo[A]) = null
}

implicit def fooInt: Foo[Int] = null

现在这正是您描述的问题,因为
(new Bar).methWithImplicits(x => x)

给出“缺少参数类型”。

所以我们想要做的是将隐式参数移动到“后面”
显式提供的函数,以便 Scala 首先看到隐式。好,
我们可以做到这一点的一种方法是添加一个额外的间接层:
class Bar {
def methWithImplicits2[A](implicit foo: Foo[A]) = new {
def apply[B](f: A => B) = null
}
}

(new Bar).methWithImplicits2.apply(x => x)

这有效,尽管语法不是那么漂亮。您可能会考虑的一种方式
漂亮的语法是看看你当前的设计,看看你是否可以偷偷摸摸
隐式进入任何“早期”阶段。例如,由于 mapValuesStrict方法只有在隐式被使用后才有意义
提供,您可以使隐式成为对象的属性而不是
传递给方法。

但是如果这在您的设计中不方便,您可以使用额外的隐式
转换偷偷回来。这是我们想要做的:
implicit def addFoo[A](bar: Bar)(implicit foo: Foo[A]) = new {
def methWithImplicits3[B](f: A => B) = null
}

但不幸的是,我怀疑是 Scala 中的一个错误导致它
搜索一个过于多态的隐式值,导致它提示:
could not find implicit value for parameter foo: test.Foo[A]

这只发生在使用隐式转换时,这就是为什么我认为它是一个
漏洞。所以,我们可以更进一步:(并且,需要 -Xexperimental对于依赖方法类型):
trait FooWrapper {
type AA
val foo: Foo[AA]
}

implicit def wrapFoo[A](implicit theFoo: Foo[A]) = new FooWrapper {
type AA = A
val foo = theFoo
}

implicit def addFoo(bar: Bar)(implicit foo: FooWrapper) = new {
def methWithImplicits3[B](f: foo.AA => B) = null
}

现在
(new Bar).methWithImplicits3(x => x)

完美运行;)

更新

在您的特定情况下,我认为您最好的选择是将隐式处理成 enhanceGenTraversable但是,唉,需要同样的 hack 来解决可能的错误:
// Notice `ev` is now a field of the class
class EnhancedGenTraversableLike[A, Repr <: GenTraversable[A], T, U]
(self: GenTraversableLike[A, Repr], ev: A <:< (T, U))
{
def mapValuesStrict[R, That](f: U => R)(implicit bf: CanBuildFrom[Repr, (T, R), That]) = {
val b = bf(self.asInstanceOf[Repr])
b.sizeHint(self.size)
for ((k: T, v: U) <- self) b += k -> f(v)
b.result
}
}

// The Hack
trait WrappedPairBound[A] {
type TT
type UU
val bound: A <:< (TT, UU)
}

implicit def wrapPairBound[A,T,U](implicit ev: A <:< (T,U)) = new WrappedPairBound[A] {
type TT = T
type UU = U
val bound = ev
}

// Take the implicit here
implicit def enhanceGenTraversableLike[A, Repr <: GenTraversable[A]]
(self: GenTraversableLike[A, Repr])(implicit ev: WrappedPairBound[A]) =
new EnhancedGenTraversableLike[A, Repr, ev.TT, ev.UU](self, ev.bound)

关于Scala:错误:缺少参数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9089893/

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