16. let の変換規則
.
変換規則
..
.
T(return e, C) = C(b.Return(e))
T(let p = e in ce, C) = T(ce, λv.C(let p = e in v))
.
let の変換例
..
.
T(let x = 42 in return x, λv1.v1)
−→T(return x, λv2.(λv1.v1)(let x = 42 in v2))
−→(λv2.(λv1.v1)(let x = 42 in v2))(b.Return(x))
−→(λv1.v1)(let x = 42 in b.Return(x))
−→let x = 42 in b.Return(x)
17. if の変換規則
.
変換規則
..
.
{| cexpr |} ≡ T(cexpr, λv.v)
T(return e, C) = C(b.Return(e))
T(if e then ce1 else ce2, C) = C(if e then {| ce1 |} else {| ce2 |})
T(if e then ce, C) = C(if e then {| ce |} else b.Zero())
.
if の変換例
..
.
T(if c then return 42, λv1.v1)
−→(λv1.v1)(if c then {| return 42 |} else b.Zero())
−→(λv1.v1)(if c then T(return 42, λv2.v2) else b.Zero())
−→(λv1.v1)(if c then (λv2.v2)(b.Return(42)) else b.Zero())
−→(λv1.v1)(if c then b.Return(42) else b.Zero())
−→if c then b.Return(42) else b.Zero()
31. 例外による実装
.
ビルダー
..
.
type ReturnExn'T(xs: 'T seq) =
inherit System.Exception()
member this.Value = xs
type SeqBuilder'T() =
member this.Yield(x: 'T) = Seq.singleton x
member this.Return(x: 'T) =
raise (ReturnExn(Seq.singleton x))
member this.Combine(xs: 'T seq, cont: unit - 'T seq) =
Seq.append xs (cont ())
member this.Delay(f: unit - 'T seq) = f
member this.Run(f: unit - 'T seq) =
try f () with
| :? ReturnExn'T as e - e.Value
let seq2'T = SeqBuilder'T() // 型関数
32. 例外による実装
.
使用例
..
.
seq2 { yield 1; yield 2 };;
val it : seqint = seq [1; 2]
seq2 { return 1; return 2 };;
val it : seqint = seq [1]
おぉ!
35. 改良版
.
Combine でも ReturnExn を捕捉
..
.
type SeqBuilder'T() =
member this.Yield(x: 'T) = Seq.singleton x
member this.Return(x: 'T) =
raise (ReturnExn(Seq.singleton x))
member this.Combine(xs: 'T seq, cont: unit - 'T seq) =
try
Seq.append xs (cont ())
with
| :? ReturnExn'T as e -
raise (ReturnExn(Seq.append xs e.Value))
member this.Delay(f: unit - 'T seq) = f
member this.Run(f: unit - 'T seq) =
try f () with
| :? ReturnExn'T as e - e.Value
let seq2'T = SeqBuilder'T()
38. 状態変数による実装
.
ビルダー
..
.
type SeqBuilder() =
let mutable isExit = false
member this.Yield(x) = Seq.singleton x
member this.Return(x) =
isExit - true
Seq.singleton x
member this.Combine(xs, cont) =
if isExit then xs else Seq.append xs (cont ())
member this.Delay(f) = f
member this.Run(f) =
let res = f ()
isExit - false
res
let seq2 = SeqBuilder()
39. 状態変数による実装
.
使用例
..
.
seq2 { yield 1; yield 2 };;
val it : seqint = seq [1; 2]
seq2 { return 1; return 2 };;
val it : seqint = seq [1]
seq2 { yield 1; return 2; return 3 };;
val it : seqint = seq [1; 2]
おぉ!
45. 状態引数による実装
.
ビルダー
..
.
type FlowControl = Break | Continue
type SeqBuilder() =
member this.Yield(x) = Seq.singleton x, Continue
member this.Return(x) = Seq.singleton x, Break
member this.Combine((xs, st), cont) =
match st with
| Break - xs, Break
| Continue -
let ys, st = cont ()
Seq.append xs ys, st
member this.Delay(f) = f
member this.Run(f) = f () | fst
let seq2 = SeqBuilder()
46. 状態引数による実装
.
使用例
..
.
seq2 { yield 1; yield 2 };;
val it : seqint = seq [1; 2]
seq2 { return 1; return 2 };;
val it : seqint = seq [1]
seq2 { yield 1; return 2; return 3 };;
val it : seqint = seq [1; 2]
おぉ!
50. 継続渡しによる実装
.
ビルダー
..
.
type SeqBuilder() =
member this.Yield(x) = fun k - k (Seq.singleton x)
member this.Return(x) = fun _ - Seq.singleton x
member this.Combine(f, cont) =
fun k - f (fun xs - cont () k | Seq.append xs)
member this.Delay(f) = f
member this.Run(f) = f () id
let seq2 = SeqBuilder()
.
使用例
..
.
seq2 { yield 1; yield 2 };;
val it : seqint = seq [1; 2]
seq2 { return 1; return 2 };;
val it : seqint = seq [1]
seq2 { yield 1; return 2; return 3 };;
val it : seqint = seq [1; 2]