scala breeze 中 collections 的隐式 Impl 方法
implicit Impl method for collections in scala breeze
我在 SortedMap[Int, Double]
上有一个类型别名,我想有一个隐式允许我将我的 SortedMap
传递给 [=] 中的一些 built-in 函数50=],特别是 breeze.stats._
函数 variance
和 stddev
.
这是一个没有隐含的工作示例:
package com.soquestion
import breeze.linalg._
import breeze.stats._
import scala.collection.SortedMap
import scala.language.implicitConversions
object proof {
type Series = SortedMap[Int, Double]
def example: Double = {
val s: Series = SortedMap(1 -> 9.0, 2 -> 2.0, 3 -> 5.0, 4 -> 4.0, 5 -> 12.0, 6 -> 7.0, 7 -> 8.0, 8 -> 11.0, 9 -> 9.0, 10 -> 3.0, 11 -> 7.0, 12 -> 4.0, 13 -> 12.0, 14 -> 5.0, 15 -> 4.0, 16 -> 10.0, 17 -> 9.0, 18 -> 6.0, 19 -> 9.0, 20 -> 4.0)
stddev(s.values)
}
}
运行 在 sbt console
scala> com.soquestion.proof.example
res0: Double = 3.0607876523260447
我想要的是不必指定 .values
,只需调用 stddev(s)
和 variance(s)
。
这是我试过的
package com.soquestion
import breeze.linalg._
import breeze.stats._
import scala.collection.SortedMap
import scala.language.implicitConversions
object proof {
// Implicitly convert the SortedMap, or any map, to a DenseVector[Double]
implicit def series2DenseVector(s: Traversable[(Int, Double)]): DenseVector[Double] = {
DenseVector(s.map(_._2).toArray)
}
type Series = SortedMap[Int, Double]
def example: Double = {
val s: Series = SortedMap(1 -> 9.0, 2 -> 2.0, 3 -> 5.0, 4 -> 4.0, 5 -> 12.0, 6 -> 7.0, 7 -> 8.0, 8 -> 11.0, 9 -> 9.0, 10 -> 3.0, 11 -> 7.0, 12 -> 4.0, 13 -> 12.0, 14 -> 5.0, 15 -> 4.0, 16 -> 10.0, 17 -> 9.0, 18 -> 6.0, 19 -> 9.0, 20 -> 4.0)
stddev(s) // <--- compiler error here
}
}
但是我得到一个编译器错误
could not find implicit value for parameter impl: breeze.stats.stddev.Impl[com.soquestion.proof.Series,VR]
通过 breeze 文档我无法找到一个很好的例子来说明我需要提供什么。理想情况下,我想做一个隐式,允许我在没有多个隐式的情况下同时调用 stdev
和 variance
。
我确实看到了问题 Scala Breeze DenseVector Implicit failure,但我不知道它如何适用于这种情况。
完整格式的答案基于下面@dlwh 的答案,以防将来有人需要它
package com.soquestion
import breeze.linalg.support._
import breeze.linalg.support.CanTraverseValues._
import breeze.stats._
import scala.annotation.tailrec
import scala.collection.SortedMap
import scala.language.implicitConversions
object proof {
type Series = SortedMap[Int, Double]
def example: Double = {
// ideally this implicit would go in a scope higher up so it could be
// brought in wherever it's needed, but this works for a sample
implicit object SeriesIter extends CanTraverseValues[Series, Double] {
def isTraversableAgain(from: Series) = true
def traverse(from: Series, fn: ValuesVisitor[Double]): Unit = {
@tailrec def traverser(idx: Int, t: Array[Double]): Unit = {
if (idx == 1) fn.visit(t.head)
else {
fn.visit(t.head)
traverser(idx - 1, t.tail)
}
}
val v: Array[Double] = from.values.toArray
fn.zeros(0, 0d)
traverser(v.size, v)
}
}
val s: Series = SortedMap(1 -> 9.0, 2 -> 2.0, 3 -> 5.0, 4 -> 4.0, 5 -> 12.0, 6 -> 7.0, 7 -> 8.0, 8 -> 11.0, 9 -> 9.0, 10 -> 3.0, 11 -> 7.0, 12 -> 4.0, 13 -> 12.0, 14 -> 5.0, 15 -> 4.0, 16 -> 10.0, 17 -> 9.0, 18 -> 6.0, 19 -> 9.0, 20 -> 4.0)
stddev(s)
}
}
文档在这方面可能会更好,我真希望我能让错误消息更有帮助。
如果您查看 stddev
's source,您会发现它需要 variance.Impl
的实现,这需要 meanAndVariance.Impl
,可以为具有 CanTraverseValues[T, Double]
隐含。默认情况下,集合有一个 CanTraverseValues
隐式,但仅在包含的类型上,而不是 Scala 的 Map
类型的值。
实施 CanTraverseValues 和 CanMapValues 将启用最简单的 UFunc。
Scala 通常不会 "chain" 隐含,这就是为什么你的 proof
示例不起作用。
我在 SortedMap[Int, Double]
上有一个类型别名,我想有一个隐式允许我将我的 SortedMap
传递给 [=] 中的一些 built-in 函数50=],特别是 breeze.stats._
函数 variance
和 stddev
.
这是一个没有隐含的工作示例:
package com.soquestion
import breeze.linalg._
import breeze.stats._
import scala.collection.SortedMap
import scala.language.implicitConversions
object proof {
type Series = SortedMap[Int, Double]
def example: Double = {
val s: Series = SortedMap(1 -> 9.0, 2 -> 2.0, 3 -> 5.0, 4 -> 4.0, 5 -> 12.0, 6 -> 7.0, 7 -> 8.0, 8 -> 11.0, 9 -> 9.0, 10 -> 3.0, 11 -> 7.0, 12 -> 4.0, 13 -> 12.0, 14 -> 5.0, 15 -> 4.0, 16 -> 10.0, 17 -> 9.0, 18 -> 6.0, 19 -> 9.0, 20 -> 4.0)
stddev(s.values)
}
}
运行 在 sbt console
scala> com.soquestion.proof.example
res0: Double = 3.0607876523260447
我想要的是不必指定 .values
,只需调用 stddev(s)
和 variance(s)
。
这是我试过的
package com.soquestion
import breeze.linalg._
import breeze.stats._
import scala.collection.SortedMap
import scala.language.implicitConversions
object proof {
// Implicitly convert the SortedMap, or any map, to a DenseVector[Double]
implicit def series2DenseVector(s: Traversable[(Int, Double)]): DenseVector[Double] = {
DenseVector(s.map(_._2).toArray)
}
type Series = SortedMap[Int, Double]
def example: Double = {
val s: Series = SortedMap(1 -> 9.0, 2 -> 2.0, 3 -> 5.0, 4 -> 4.0, 5 -> 12.0, 6 -> 7.0, 7 -> 8.0, 8 -> 11.0, 9 -> 9.0, 10 -> 3.0, 11 -> 7.0, 12 -> 4.0, 13 -> 12.0, 14 -> 5.0, 15 -> 4.0, 16 -> 10.0, 17 -> 9.0, 18 -> 6.0, 19 -> 9.0, 20 -> 4.0)
stddev(s) // <--- compiler error here
}
}
但是我得到一个编译器错误
could not find implicit value for parameter impl: breeze.stats.stddev.Impl[com.soquestion.proof.Series,VR]
通过 breeze 文档我无法找到一个很好的例子来说明我需要提供什么。理想情况下,我想做一个隐式,允许我在没有多个隐式的情况下同时调用 stdev
和 variance
。
我确实看到了问题 Scala Breeze DenseVector Implicit failure,但我不知道它如何适用于这种情况。
完整格式的答案基于下面@dlwh 的答案,以防将来有人需要它
package com.soquestion
import breeze.linalg.support._
import breeze.linalg.support.CanTraverseValues._
import breeze.stats._
import scala.annotation.tailrec
import scala.collection.SortedMap
import scala.language.implicitConversions
object proof {
type Series = SortedMap[Int, Double]
def example: Double = {
// ideally this implicit would go in a scope higher up so it could be
// brought in wherever it's needed, but this works for a sample
implicit object SeriesIter extends CanTraverseValues[Series, Double] {
def isTraversableAgain(from: Series) = true
def traverse(from: Series, fn: ValuesVisitor[Double]): Unit = {
@tailrec def traverser(idx: Int, t: Array[Double]): Unit = {
if (idx == 1) fn.visit(t.head)
else {
fn.visit(t.head)
traverser(idx - 1, t.tail)
}
}
val v: Array[Double] = from.values.toArray
fn.zeros(0, 0d)
traverser(v.size, v)
}
}
val s: Series = SortedMap(1 -> 9.0, 2 -> 2.0, 3 -> 5.0, 4 -> 4.0, 5 -> 12.0, 6 -> 7.0, 7 -> 8.0, 8 -> 11.0, 9 -> 9.0, 10 -> 3.0, 11 -> 7.0, 12 -> 4.0, 13 -> 12.0, 14 -> 5.0, 15 -> 4.0, 16 -> 10.0, 17 -> 9.0, 18 -> 6.0, 19 -> 9.0, 20 -> 4.0)
stddev(s)
}
}
文档在这方面可能会更好,我真希望我能让错误消息更有帮助。
如果您查看 stddev
's source,您会发现它需要 variance.Impl
的实现,这需要 meanAndVariance.Impl
,可以为具有 CanTraverseValues[T, Double]
隐含。默认情况下,集合有一个 CanTraverseValues
隐式,但仅在包含的类型上,而不是 Scala 的 Map
类型的值。
实施 CanTraverseValues 和 CanMapValues 将启用最简单的 UFunc。
Scala 通常不会 "chain" 隐含,这就是为什么你的 proof
示例不起作用。