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]) = new EnhancedGenTraversableLike[A,Repr](self)
这是我去使用它时会发生什么:
scala> List((1,2),(2,3),(3,4),5)).mapValuesstrict((_:Int).toString) res0: List[(Int,java.lang.String)] = List((1,5)) scala> List((1,5)).mapValuesstrict(x => x.toString) <console>:13: error: missing parameter type List((1,5)).mapValuesstrict(x => x.toString) ^
因此Scala无法确定x的类型.
This answer表示Scala不使用一个参数来解析另一个参数,但单独的参数列表可以解决问题.然而,在我的情况下,这并不容易,因为类型信息可以在隐式参数中找到.
有没有办法解决这个问题,这样我每次调用方法时都不必指定类型?
更新:根据Owen的建议,我最终创建了一个特定于可遍历对的丰富类:
class EnrichedPairGenTraversableLike[T,Repr <: GenTraversable[(T,U)]](self: GenTraversableLike[(T,Repr]) { def mapValuesstrict[R,That](f: U => R)(implicit bf: CanBuildFrom[Repr,v: U) <- self) b += k -> f(v) b.result } } implicit def enrichPairGenTraversableLike[T,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中,但是,唉,需要同样的黑客来解决可能的错误:
// 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]) = { 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,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)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。