tateT[M, Int, a]})#l] } def m[M[_]: Monad] { Applicative[({type l[a] = StateT[M, Int, a]})#l] Monad[({type l[a] = StateT[M, Int, a]})#l] MonadState[({type f[s, a] = StateT[M, s, a]})#f, Int] } def state() { val state: State[String, Int] = State((x: String) => (x + 1, 0)) val eva l: Int = state.eva l("") state.flatMap(_ => state) } }
哇塞!这是什么地干活?我只能无奈的告诉你:其实什么也没干,可以在即时编译器里看看:
import Scalaz._ import scala.language.higherKinds def f[M[_]: Functor] { Functor[({type l[a] = StateT[M, Int, a]})#l] } //> f: [M[_]](implicit evidence$2: scalaz.Functor[M])Unit
def m[M[_]: Monad] { Applicative[({type l[a] = StateT[M, Int, a]})#l] Monad[({type l[a] = StateT[M, Int, a]})#l] MonadState[({type f[s, a] = StateT[M, s, a]})#f, Int] } //> m: [M[_]](implicit evidence$3: scalaz.Monad[M])Unit
def state() { val state: State[String, Int] = State((x: String) => (x + 1, 0)) val eva l: Int = state.eva l("") state.flatMap(_ => state) } //> state: ()Unit
f[List] m[List] state
全部返回Unit。我想它只是示范了如何取得一些type class的StateT实例吧。我们知道,获取了一些type class的StateT实例后就可以对StateT施用这些type class的方法函数了。下面是如何获取这些实例以及简单的type class函数引用:
1 //Functor实例
2 val fs = Functor[({type l[a] = StateT[List, Int, a]})#l] 3 //> fs : scalaz.Functor[[a]scalaz.IndexedStateT[[+A]List[A],Int,Int,a]] = scala 4 //| z.StateTInstances1$$anon$1@12468a38
5 State[Int,Int] {s => (s+1,s)} //> res0: scalaz.State[Int,Int] = scalaz.package$State$$anon$3@1aa7ecca
6 val st = StateT[List, Int, Int](s => List((s,s)))//> st : scalaz.StateT[List,Int,Int] = scalaz.package$StateT$$anon$1@6572421
7 fs.map(st){a => a + 1}.run(0) //> res1: List[(Int, Int)] = List((0,1)) 8 //MonadState实例
9 val ms = MonadState[({type f[s, a] = StateT[List, s, a]})#f, Int] 10 //> ms : scalaz.MonadState[[s, a]scalaz.IndexedStateT[[+A]List[A],s,s,a],Int] = 11 //| scalaz.StateTInstances1$$anon$1@3c19aaa5
12 ms.state(1).run(0) //> res2: List[(Int, Int)] = List((0,1)) 13 //Monad实例
14 val monad = Monad[({type l[a] = StateT[List, Int, a]})#l] 15 //> monad : scalaz.Monad[[a]scalaz.IndexedStateT[[+A]List[A],Int,Int,a]] = scal 16 //| az.StateTInstances1$$anon$1@689604d9
17 monad.bind(st){a => StateT(a1 => List((a1,a)))}.run(0) 18 //Applicative实例 //> res3: List[(Int, Int)] = List((0,0))
19 val ap = Applicative[({type l[a] = StateT[List, Int, a]})#l] 20 //> ap : scalaz.Applicative[[a]scalaz.IndexedStateT[[+A]List[A],Int,Int,a]] = s 21 //| calaz.StateTInstances1$$anon$1@18078bef
22 ap.point(0).run(0) //> res4: List[(Int, Int)] = List((0,0))
这个state()函数呢?更是摸不着头脑,可能纯是从类型匹配方面示范吧。我们看看它的内里都干了什么:
1 // def state() { 2 //构建一个State实例。每次它的状态会加个!符号
3 val state: State[String, Int] = State((x: String) => (x + "!", 0)) 4 //> state : scalaz.State[String,Int] = scalaz.package$State$$anon$3@1e67b872 5 //运算值不变
6 val eva l: Int = state.eva l("") //> eva l : Int = 0 7 //连续两次运行状态运算函数。加两个!
8 state.flatMap(_ => state).run("haha") //> res0: scalaz.Id.Id[(String, Int)] = (haha!!,0) 9 // }
那么StateTUsage.scala里其它例子呢?又离不开什么List,Tree,ADT...,太脱离现实了。还是介绍些实际点的例子吧。最好能把在现实应用中如何选择使用State的思路过程示范一下。曾经看到过一个例子是这样的:查询一个网页的跟帖人信息;维护一个cache,存储5分钟内查过的信息;如果在cache里不存在就从数据库里读取,同时更新cache。我们用伪代码来示范。由于我们选择immutable cache,所以按FP惯用方式传入当前cache,返回新cache:
trait Cache trait FollowerState def followerState(user: Stri |