2015-11-20 47 views
2

我在SortedMap[Int, Double]上有一個類型別名,我想隱式地讓我通過我的SortedMap一些微風中的內置函數,特別是breeze.stats._函數variancestddev隱式Impl方法在scala微風中收藏

這裏的工作示例不implicits:

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] 

通過微風文檔去編譯錯誤我是不是能找到什麼隱含的,我需要一個很好的例子提供。理想情況下,我希望做一個暗示,這將允許我呼叫stdevvariance而沒有多重含義。

我的確看到了問題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) 
    } 
} 
+0

提出了一個更簡單的實現(實際上沒有仔細檢查它,但我認爲是正確的) – dlwh

回答

2

該文檔可多爲了這個美好的,我也希望我能做出的錯誤消息的更多很有幫助。

如果你看stddev's source,你會看到,它需要的variance.Impl的實現,這需要一個meanAndVariance.Impl,可爲具有CanTraverseValues[T, Double]隱含的任何類型來提供。默認情況下,集合有一個隱含的CanTraverseValues,但僅限於包含的類型,而不是scala的Map類型的值。實現CanTraverseValues和CanMapValues將啓用大多數微風UFuncs。

斯卡拉一般不會「鏈」暗示,這就是爲什麼你的proof例子不起作用。

+1

謝謝!我最終添加了以下內容,並很好地解決了這個問題。 隱式對象mapLikeIter extends CanTraverseValues [系列,雙精度] {def} isTraversableAgain(from:Series)= true def遍歷(from:Series,fn:ValuesVisitor [Double]):單位= {tail} def遍歷器(idx:Int,t:Array [Double]):單位= {如果(idx == 1)fn.visit(t.head) else { fn.visit(t。頭) 橫移(IDX - 1,t.tail) } } VALν:數組[雙] = from.values.toArray fn.zeros(0,0D) 橫移(ⅴ。尺寸,v) } } –