设计模式 – 双折叠的功能模式
发布时间:2020-12-16 19:22:04 所属栏目:安全 来源:网络整理
导读:让玩具级的柜台如: class Counter private( val next: Int,val str2int: Map[String,Int] ) { def apply( str: String ): (Int,Counter) = str2int get str match { case Some(i) = ( i,this ) case None = ( next,new Counter( next+1,str2int + (str - ne
让玩具级的柜台如:
class Counter private( val next: Int,val str2int: Map[String,Int] ) { def apply( str: String ): (Int,Counter) = str2int get str match { case Some(i) => ( i,this ) case None => ( next,new Counter( next+1,str2int + (str -> next) ) ) } } object Counter { def apply() = new Counter( 0,Map() ) } 此类提供String和自然数之间的映射,每次查询新String时,映射都会延迟扩展. 然后我可以编写一个方法,它可以在Iq的Seq中转换字符串的Seq,在遍历期间更新映射.我得到的第一个实现是foldLeft: def toInt( strs: Seq[String],counter: Counter ): ( Seq[Int],Counter ) = strs.foldLeft( (Seq[Int](),counter) ) { (result,str) => val (i,nextCounter) = result._2( str ) ( result._1 :+ i,nextCounter ) } 这按预期工作: val ss = Seq( "foo","bar","baz","foo","baz" ) val is = toInt( ss,Counter() )._1 //is == List(0,1,2,2) 但我对于实施并不是很满意.问题是我折叠了两个不同的值.是否有一个函数式编程模式来简化实现? 解决方法
您正在寻找的模式是State monad:
import scalaz._ import Scalaz._ case class Counter(next: Int = 0,str2int: Map[String,Int] = Map()) { def apply( str: String ): (Counter,Int) = (str2int get str) fold ( (this,_),(new Counter(next+1,str2int + (str -> next)),next) )} type CounterState[A] = State[Counter,A] def count(s: String): CounterState[Int] = state(_(s)) def toInt(strs: Seq[String]): CounterState[Seq[Int]] = strs.traverse[CounterState,Int](count) 类型注释是不幸的,也许它可以以某种方式消除.无论如何,这是一个它的运行: scala> val ss = Seq( "foo","baz" ) ss: Seq[java.lang.String] = List(foo,bar,baz,foo,baz) scala> val is = toInt(ss) ! Counter() is: Seq[Int] = List(0,2) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |