2014-10-01 58 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