私は家で引きこもってるけど!
State
状態を保持する計算に用いられます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val s = for { | |
i <- init[Int] | |
_ <- modify[Int](_ |+| 5) | |
j <- gets[Int, Int](_ |+| 5) | |
} yield i |+| j | |
s ! 0 assert_=== 10 | |
s ! 5 assert_=== 20 |
Stateは!で値を、~>で状態を、applyで両方をとりだせます。
値、状態を取り出すときには、初期状態を与えなければなりません。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val s = (put(5) >|> state[Int, Int](s => (s * 2, s + 10))) | |
s ! mzero[Int] assert_=== 15 | |
s ~> mzero[Int] assert_=== 10 | |
s(mzero[Int]) assert_=== (10, 15) |
値や状態を操作するための関数はStatesに定義されています。
init
状態で値を初期化します。
put
状態を上書きします。
gets
状態から値を更新します。
modify
状態から状態を更新します。
state
状態から値と状態を更新します。
IdentityにもStateを作る関数が定義されています。
state
呼び出し元を初期値にします。
constantState
呼び出し元を初期値にし、初期状態を与えます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val s = for { | |
i <- 10.state[Int] | |
j <- gets[Int, Int](_ |+| 5) | |
k <- 10.constantState(5) | |
} yield i |+| j |+| k | |
s ! 5 assert_=== 30 | |
s ! 10 assert_=== 35 | |
s ~> 0 assert_=== 5 |
State#withsは入力される状態を更新します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
init[Int].withs(_ |+| 5) ~> 5 assert_=== 10 | |
5.state[Int].withs(_.times(2)) ~> 5 assert_=== 10 | |
put(5).withs(_ |+| 100) ~> 10 assert_=== 5 |
StateT
モナド変換子版もあります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val s = for { | |
i <- stateT[Option, Int, Int](_.some <|*|> 100.some) | |
j <- stateT[Option, Int, Int](s => (s + 100).some <|*|> s.some) | |
} yield i |+| j | |
s ! 100 assert_=== Some(200) | |
s ~> 100 assert_=== Some(200) |
mapsにより別のモナドにmapすることもできます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val s = for { | |
i <- stateT[Option, Int, String](_.some <|*|> "Scala".some).maps { | |
case Some((s, a)) => List((s |+| 2, a |+| "z"), (s.times(2), a |+| "ちゃん")) | |
case None => nil | |
} | |
j <- stateT[List, Int, String](s => (s |+| 100, s.shows |+| "倍かわいい").pure[List]) | |
} yield i |+| j | |
s ! 10 assert_=== List("Scalaz12倍かわいい", "Scalaちゃん20倍かわいい") |
Writerは結合していくことしか出来ませんでしたが、Stateではもう少し自由度が高いというイメージです。
ScalaはvarがあるからStateモナドとかいらないのでは?と思っていましたが、実際に調べて書いてみると可変な参照とはまた違ったもので、これはこれで使い方がありそうです。
STモナドはいりません。
0 件のコメント:
コメントを投稿