generated at
Kokaの例: State

state effectを定義
koka(ts)
effect state<a> fun get() : a fun set(x: a) : ()
2つのoperationを定義している


与えられた数値から0まで足し合わす関数を定義
koka(ts)
fun sumdown(sum: int = 0): <state<int>,div> int val i = get() if i <= 0 then sum else set(i - 1) sumdown(sum + i)
val は定数宣言
内部で get() / set() を使っているので、 state を持ち、
再帰しているので div も持つ
この時点では、どこかからgetして、どこかにsetする、と言ってるだけmrsekut
実際にその保存先がどこなのかは、 sumdown は言及しない
interfaceだけ書き、実装は書かれていない


state effect用のhandlerを定義
koka(ts)
fun state(init: a, action: () -> <state<a>,div|e> b): <div|e> b var st := init with handler fun get() st fun set(i) st := i action()
var でmutableな変数を宣言
get はその変数の値を読むだけ、 set はその変数を更新する
あえてもう少し明示的に書くと
koka(js)
fun state(init: a, action: () -> <state<a>,div|e> b): <div|e> b var st := init with handler ctl get() val f = fn() { st } resume(f()) ctl set(i) val f = fn() { st := i } resume(f()) action()
つまり、 get set resume している


呼び出す
sumdown() という処理を、 state handler を使って呼び出す
koka(ts)
state(10) { sumdown() } // 55




他の例
以下のようにn番目のフィボナッチ数を求める関数を用意する
koka(ts)
fun fibonacci(n: int): <state<(int, int)>,div> int val (a, b): (int, int) = get() if n <= 1 then a else set( (b, a + b) ) fibonacci(n - 1)
get() の返り値部分にtype annotation付けないとerrorになったmrsekut
関数のeffect typeから推論してくれ〜、と思ったが難しいのか
valに対するannotationの付け方わからなかったけど勘で書いたらいけたmrsekut
呼び出す
koka(ts)
state((0, 1)) { fibonacci(50) } // 7778742049
メモ化してる実装なので普通に速いmrsekut


参考