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()
例外による実装
.
ビルダー
..
.
type ReturnExn'T(xs: 'Tseq) =
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]
おぉ!
改良版
.
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()
状態変数による実装
.
ビルダー
..
.
type SeqBuilder() =
letmutable 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]
おぉ!
状態引数による実装
.
ビルダー
..
.
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]
おぉ!
継続渡しによる実装
.
ビルダー
..
.
type SeqBuilder() =
memberthis.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]
各ライブラリでの実装状況
.
検証用コード例
..
.
let xs =[30; 10; 15; 21; -1; 50]
builder {
let i = ref 0
while !i xs.Length do
if xs.[!i] = -1 then
return false
incr i
return true
}
コンパイルできるか
false 的なものが返るか
57.
各ライブラリでの実装状況
.
検証用コード例展開
..
.
let b =builder
b.Run(
b.Delay(fun () -
let i = ref 0
b.Combine(
b.While(
(fun () - !i xs.Length),
b.Delay(fun () -
b.Combine(
(if xs.[!i] = -1 then b.Return(false)
else b.Zero()),
b.Delay(fun () - incr i; b.Zero())))),
b.Delay(fun () - b.Return(true)))))