ng, cache: Cache): (Cache, FollowerState) = { val (c1,ofs) = checkCache(user,cache) //检查cache里有没有user资料 //c1是新cache,更新了hit或miss count
ofs match { //在cache里找到否
case Some(fs) => (c1,fs) //找到就返回fs和新cache c1
case None => retrieve(user,c1) //找不到就从数据库里重新读取
} } //检查cache,更新cache hit/miss count
def checkCache(user: String, cache: Cache): (Cache, Option[FollowerState]) = ... //从数据库读取user资料,更新加入cache
def retrieve(user: String, cache: Cache): (Cache, FollowerState) = ...
这个cache不就是一种状态嘛。我们现在需要考虑怎么在上面的函数里使用State Monad来维护这个cache。我们先耍点手段,来点函数款式变形(transformation):
def followerState(user: String, cache: Cache): (Cache, FollowerState) def followerState(user: String)(cache: Cache): (Cache, FollowerState) def followerState(user: String): Cache => (Cache, FollowerState)
先用curry分开参数,再部分施用(partially apply)就形成了新的函数款式。其它两个函数也一样:
def checkCache(user: String): Cache => (Cache, Option[FollowerState]) = ... def retrieve(user: String): Cache => (Cache, FollowerState) = ...
现在followerState可以这样写:
def followerState(user: String): Cache => (Cache, FollowerState) = cache => { val (c1,ofs) = checkCache(user,cache) ofs match { case Some(fs) => (c1,fs) case None => retrieve(user,c1) } }
现在这个Cache=>(Cache,FollowerState)不就是一个状态运算函数嘛,Cache是状态,FollowerState是运算值。我们把它包嵌在State内:
def followerState(user: String): State[Cache,FollowerState] = State { cache => { val (c1,ofs) = checkCache(user,cache) ofs match { case Some(fs) => (c1,fs) case None => retrieve(user,c1) } } }
如果把其它函数款式也调整过来,都返回State类型:
def checkCache(user: String): State[Cache,Option[FollowerState]] = ... def retrieve(user: String): State[Cache,FollowerState] = ...
那么我们可以用for-comprehension:
def followerState(user: String): State[Cache,FollowerState] = for { optfs <- checkCache(user) fs <- optfs match { case Some(fs) => State{ s => (s, fs) } case None => retrieve(user) } } yield fs
程序看来简明很多。我们可以这样调用获取查询结果:
followerState("Johny Depp").eva l(emptyCache)
|