2014-10-01 222 views
0

我試圖簡化一個真實的代碼,但沒有太多。如何遍歷scalaz

給出下面的輸入,執行的f和g只是爲例子,真正的一個比較複雜

scala> val m = Map("a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4) 
m: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3, d -> 4) 

scala> val f : Int => Option[Int] = i => if (i % 2 == 0) Some(i) else None 
f: Int => Option[Int] = <function1> 

scala> val g = (a:Int, l:List[Int]) => a :: l 
g: (Int, List[Int]) => List[Int] = <function2> 

下面的過程是:

m.foldLeft(List[Int]()) { case (l, (k, v)) => 
    f(v) match { 
    case Some(w) => g(w, l) 
    case None => l 
    } 
} 

是否有可能使用scalaz來更好地揭示意圖?

我thinkink約m.traverseS

回答

0

如果g確實需要處理整個List[Int]然後我馬上想到了Endo(需要稍微改寫g):

val f: Int => Iterable[Int] = ??? 
val g: Int => Endo[List[Int]] = ??? 

val m = Map("a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4) 

Foldable[List].fold(m.values.toList flatMap f map g).apply(List[Int]()) 

我不知道那是多少儘管如此。

+0

如上所述,f和g代碼僅僅是舉例,只有簽名是重要的。 – 2014-10-06 14:10:52

+0

這就是爲什麼我故意寫我的例子只使用簽名。一個選項[Int]實際上是一個Iterable [Int](甚至有一個隱式的)和一個(Int,List [Int])=> List [Int]總是可以寫成Int => Endo [List [Int ]。所以這些簽名對於f和g的任何實現都是有效的。 – lmm 2014-10-06 15:24:01

0
m.collect{ case(s, i) => (s, f(i))} 
.filter{ case (s,i) => i.isDefined } 
.toList 
.traverseS({s => State({ l: List[Int] => (g(s._2.get, l),())})}) 
.run(Nil) 
._1 
.reverse