SlideShare une entreprise Scribd logo
1  sur  72
Télécharger pour lire hors ligne
yield and return
∼ Poor English ver. ∼
bleis-tift
July 27, 2014
Self introduction
https://twitter.com/bleis
https://github.com/bleis-tift
Yuru-Fuwa F#er in Nagoya
I like static typed functional languages
Agenda
Part1: Computation Expression
Part2:Dierence of yield and return
∼considerations∼
Part3:Dierence of yield and return
∼implementations∼
Part4:Conclusion
I will talk about how to implement computation
expression.
Part1: Computation Expression
Computation expression is...
expression that extends normal F# grammer and
provides some customize points
able to dene an user dene process
.
the grammer of F#
..
.
let someFunc a b =
let x = f a
let y = g b
x + y
.
computation expression
..
.
let someFunc a b = builder {
let! x = f a
let! y = g b
return x + y
}
Usages
Remove nests of match expressions for option
Hide parameters for state
Remove nests of function call for async proc
and so on...
But I will skip these topics today.
The way of implementation
The computation exprs are implemented by
some translation rules in F#
Needless any interfaces
Most important thing is which translated exprs are
compilable
.
.
grammer of computation expr
translate
normal grammer
Let's look at some translation rules together!
Notation
Sans-Serif Code of F#. ex) fun x - x
Serif meta Variables. ex) cexpr
Itaric The part related to the translation. ex)
T(e, C)
Translation rule (most outside)
.
. builder-expr { cexpr }
F#compiler translates following:
.
. let b = builder-expr in {| cexpr |}
b is a fresh variable.
builder-expr
Just a normal expression
Builder is evaluated only once
Dene methods called at runtime into builder
type
All methods are dened as instance method
{| ... |}
Translate expr to core language grammer
ex) {| cexpr |} ... translate cexpr
See below for further detais
cexpr
The most outer target of translation
Other computation expr is represented by ce
cexpr is translated by Delay-trans, Quote-trans,
Run-trans if necessary
Representation of the translation rules
The translation rules are described by T-notation
.
T-notation
..
.T(e, C)
e:The computation expr that will be translated
C:The context that was translated
Find the translation rule that match e, and translate
it
T-notation of {| cexpr |}
.
T-notation
..
. {| cexpr |} ≡ T(cexpr, λv.v)
λv.v is anonymous function
before dot: the parameter
after dot: the function body
v is the translated expression
Function application is done at compile-time
(not run-time)
Trans rule for return
.
Trans rule
..
. T(return e, C) = C(b.Return(e))
if cexpr is return 42 then:
.
Example
..
.
T(return 42, λv.v)
−→(λv.v)(b.Return(42))
−→b.Return(42)
Complete!
Trans rule for let
.
Trans rules
..
.
T(return e, C) = C(b.Return(e))
T(let p = e in ce, C) = T(ce, λv.C(let p = e in v))
.
Example
..
.
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)
Trans rule of if
.
Trans rules
..
.
{| 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())
.
Example
..
.
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()
Trans rule of ce1; ce2
.
Trans rules
..
.
{| cexpr |} ≡ T(cexpr, λv.v)
T(return e, C) = C(b.Return(e))
T(ce1; ce2, C) = C(b.Combine({| ce1 |},b.Delay(fun () - {| ce2 |})))
.
Example
..
.
T(return 10; return 20, λv1.v1)
−→(λv1.v1)(b.Combine({| return 10 |},b.Delay(fun () - {| return 20 |})))
−→(λv1.v1)
(b.Combine(T(return 10, λv2.v2),b.Delay(fun () - T(return 20, λv3.v3))))
−→(λv1.v1)
(b.Combine((λv2.v2)(b.Return(10)),b.Delay(fun () - (λv3.v3)(b.Return(20)))))
−→(λv1.v1)(b.Combine(b.Return(10),b.Delay(fun () - b.Return(20))))
−→b.Combine(b.Return(10),b.Delay(fun () - b.Return(20)))
Trans rule of while.
Trans rules
..
.
{| cexpr |} ≡ T(cexpr, λv.v)
T(return e, C) = C(b.Return(e))
T(if e then ce, C) = C(if e then {| ce |} else b.Zero())
T(ce1; ce2, C) = C(b.Combine({| ce1 |},b.Delay(fun () - {| ce2 |})))
T(while e do ce, C) = T(ce, λv.C(b.While(fun () - e,b.Delay(fun () - v))))
.
Example
..
.
T (while f() do if g() then return 42 done; return 0, λv1.v1)
−→(λv1.v1)(b.Combine({| while f() do if g() then return 42 |},b.Delay(fun () - {| return 0 |})))
−→(λv1.v1)(b.Combine(
T (if g() then return 42, λv2.b.While(fun () - f(),b.Delay(fun () - v2)))
,b.Delay(fun () - b.Return(0))))
−→(λv1.v1)(b.Combine(
(λv2.b.While(fun () - f(),b.Delay(fun () - v2)))(if g() then b.Return(42) else b.Zero())
,b.Delay(fun () - b.Return(0))))
−→(λv1.v1)(b.Combine(
b.While(fun () - f(),b.Delay(fun () - if g() then b.Return(42) else b.Zero()))
,b.Delay(fun () - b.Return(0))))
−→b.Combine(b.While(fun () - f(),b.Delay(fun () - if g() then b.Return(42) else b.Zero()))
,b.Delay(fun () - b.Return(0)))
Feature of computation expr
Computation expr is similar to
do notation (Haskell)
for expression (Scala)
query expression (C#)
Dierence is computation expr has more exibility
than core language.
Computation expr is more powerful and friendly!
Part2:Dierence of yield and return
∼considerations∼
Trans rules of yield and return
.
Trans rules
..
.
T(yield e, C) = C(b.Yield(e))
T(return e, C) = C(b.Return(e))
Dierent point is only method...
Today's main theme:
Why exist the same rules?
Use properly...?
use yield for yield-like and use return for
return-like...?
use yield for collection-like, otherwise uses
return...?
What's the xxx-like!
I want to decide clearly.
Thinking about dierence between yield
and return
Reer the dictionary:
yield produce/provide
return give back
return should not be continue the following
process.
Monad's return? I don't know:)
Dierence between yield and return
.
yield
..
.
list {
yield 1
printfn done
}
.return
..
.
list {
return 1
printfn done
}
Whether or not to print done
The case of C
return
IET
yield return
yield break
query expression
select
I want to realize something like yield return and
yield break.
seq expression
return is not supported
Dicult for yield break like C#
Let's reimplements seq expression by computation
expression!
Part3:Dierence of yield and return
∼implementations∼
Problem
The trans rule is same yield and return...
Plan 1
The focus on return breaks remained process
Need to return value when called return
Throw exception that wraps returning value in
Return method and catch the exception in Run
method
Impl by exception
.
Builder
..
.
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() // type function
Impl by exception
.
Usage
..
.
 seq2 { yield 1; yield 2 };;
val it : seqint = seq [1; 2]
 seq2 { return 1; return 2 };;
val it : seqint = seq [1]
Yes!
Impl by exception
Scala uses exception for the part of implements
return and break
Looks like easy
But!
Problem
.
Bad Example
..
.
 seq2 { yield 1; return 2; return 3 };;
val it : seqint = seq [2]
In C#:
.
C#
..
.
IEnumerableint F() {
yield return 1;
yield break 2;
yield break 3; }
It returns the sequencce contains 1 and 2.
Rene version
.
Catch ReturnExn in Combine
..
.
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()
Impl by exception
If provide try-with, need to catch ReturnExn
in try-with and reraise it
Eventually, can't implement clearly
Disinclined for use to exception for control ow
Could be realized at least
Plan 2
Continue or not continue
Insert the judgement of whether to call the rest
process
impl by state eld
.
Builder
..
.
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()
impl by state eld
.
Usage
..
.
 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]
Yes!
impl by state eld
simple
looks like easy
But!
Problem
builder instance has state
use the same builder instance at the same time...
.
.
Thread A
seq2 {
yield 1
; // Combine
yield 2 // oops!
} // Run
val it : seqint = seq [1]
seq2.isExit
false
true
false
Thread B
seq2 {
return 10
} // Run
Rene version
.
Builder
..
.
type SeqBuilder() =
(* ... *)
let seq2 () = SeqBuilder()
.
Usage
..
.
 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]
Impl by state eld
Create the builder instance at every time
Can't forbid that the user share the instance
It's troublesome
Does not stand for practical use...
Plan 3
Problem: state sharing
Solution: use the argument
Carry the state by the argument, and unwrap the
state in Run method
The rest process is not called if the state is
Break in Combine method
Impl by state arg
.
Builder
..
.
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()
Impl by state arg
.
Usage
..
.
 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]
Yes!
Impl by state arg
Symmetry of the return and yield became clear
The implementation is very complex
Looks like good.
Comparison
.
Impl by exception
..
.
member this.Yield(x: 'T) = Seq.singleton x
member this.Return(x: 'T) =
raise (ReturnExn(Seq.singleton x))
.
Impl by state eld
..
.
member this.Yield(x) = Seq.singleton x
member this.Return(x) =
isExit - true
Seq.singleton x
.
Impl by state arg
..
.
member this.Yield(x) = Seq.singleton x, Continue
member this.Return(x) = Seq.singleton x, Break
Plan 4
Impl of exception: use the exception to break
the rest process
It is same to discard continuation
yield: call continuation
return: discard continuation
Impl by continuation
.Builder
..
.
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()
.Usage
..
.
 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]
Impl by continuation
Symmetry of return and yield is clear
Shortest but complex (and not dene the Bind
method)
The state arg version too
Speed Comparison
Write yield at 100,000 times and execute.
builder time
unsupported return 20.5ms
by exception 20.5ms
by state eld 20.7ms
by state arg 21.2ms
by continuation 22.6ms
seq expr 1.18ms
The dierence is less.
But builer is slower than seq expr in the rst place.
Part4 : Conclusion
Summary
The computation expression is powerful
yield and return have the same translation
rule but the meaning is dierent
The seq expression is not supported return →
reimplementation
Implementations:
by exception
by state eld (deprecated)
by state arg
by continuation
Impl status of some libraries
Design about return ex) seq/list/option
Target libraries:
FSharpx
ExtCore
FSharpPlus
Basis.Core
As of July 21, 2014
Impl status of some libraries
.
Benchmark code
..
.
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
}
Can compile it
It returns false-like value
Impl status of some libraries
.
Expanded benchmark code
..
.
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)))))
FSharpx
can't compile...
FSharpx
The type of Combine is bad.
.
Signature of Combine
..
.'a option * ('a - 'b option) - 'b option
.
Expand of error point
..
.
// 'a option * ('a - 'b option) - 'b option
b.Combine(
// bool option
(if xs.[!i] = -1 then b.Return(false) else b.Zero()),
// unit - 'a option
b.Delay(fun () - incr i; b.Zero()))
.
Correct signature
..
.'a option * (unit - 'a option) - 'a option
ExtCore
can't compile...
ExtCore
The impl of Zero is bad.
.
Implementation of Zero
..
.
member inline __.Zero () : unit option =
Some () // TODO : Should this be None?
comment...
FSharpPlus
can't compile.
Not provide While
Better choice
Basis.Core
can compile.
return false-like value.
Impl status of some libraries
No Game!
Rethink about dierence yield and return
Very few libraries implement computation expr
correctly
There is a problem to be solved before yield and
return
Should we give a semantic dierence really?
Should give if you want to take advantage of
computation expr
Should not give if you provide only Bind and
Return (like FSharpPlus)
Rethink about computation expression
Should Yield and Return receive continuation?
Compile-time translation is ecient
Can implement yield and return by now rules
I want to take this exibility
Suggestion of a Policy
The considered separately depending on the library
design
Case 1: provide monad/monad plus
Case 2: provide more general computing
Case 3: use computaion expr other than monad
Provide monad/monad plus
Provide monad
Required: Bind/Return
Optional: ReturnFrom (for convinience)
Optional: Run
Provide another builder that unwrap the value
Provide monad plus
Required: Bind/Return/Zero/Combine
Zero is mzero, Combine is mplus
Required: Delay (depends on trans rule of
Combine)
member this.Delay(f) = f ()
Provide more general computing
Separate the modules by feature
Builder module for providing Bind/Return
Builder module for providing Bind/Return/Comine
Combine is not mplus. Combine + Delay is
mplus.
Inevitably, required Delay/Run
member this.Delay(f) = f
member this.Run(f) = f ()
Optional: Zero
Support if-expr without else-clause
Use computaion expr other than monad
I have no comments:)
If provide Combine, think about yield and return
Use CustomOperation if necessary
Tasks
Report the bug to FSharpx and ExtCore
Create a library that is divided the module by
feature
Verify builder
Edication
Thanks.

Contenu connexe

Tendances

FP 201 - Unit 6
FP 201 - Unit 6FP 201 - Unit 6
FP 201 - Unit 6
rohassanie
 
C++tutorial
C++tutorialC++tutorial
C++tutorial
dips17
 
FP 201 Unit 2 - Part 3
FP 201 Unit 2 - Part 3FP 201 Unit 2 - Part 3
FP 201 Unit 2 - Part 3
rohassanie
 
Lecturer23 pointersin c.ppt
Lecturer23 pointersin c.pptLecturer23 pointersin c.ppt
Lecturer23 pointersin c.ppt
eShikshak
 
Lec 38.39 - pointers
Lec 38.39 -  pointersLec 38.39 -  pointers
Lec 38.39 - pointers
Princess Sam
 

Tendances (20)

FP 201 - Unit 6
FP 201 - Unit 6FP 201 - Unit 6
FP 201 - Unit 6
 
Pointers, virtual function and polymorphism
Pointers, virtual function and polymorphismPointers, virtual function and polymorphism
Pointers, virtual function and polymorphism
 
Rust Intro
Rust IntroRust Intro
Rust Intro
 
Pointers in C
Pointers in CPointers in C
Pointers in C
 
C++tutorial
C++tutorialC++tutorial
C++tutorial
 
Pointers+(2)
Pointers+(2)Pointers+(2)
Pointers+(2)
 
Learning C++ - Pointers in c++ 2
Learning C++ - Pointers in c++ 2Learning C++ - Pointers in c++ 2
Learning C++ - Pointers in c++ 2
 
Programming Fundamentals
Programming FundamentalsProgramming Fundamentals
Programming Fundamentals
 
Dynamic Memory Allocation in C
Dynamic Memory Allocation in CDynamic Memory Allocation in C
Dynamic Memory Allocation in C
 
Software Construction Assignment Help
Software Construction Assignment HelpSoftware Construction Assignment Help
Software Construction Assignment Help
 
FP 201 Unit 2 - Part 3
FP 201 Unit 2 - Part 3FP 201 Unit 2 - Part 3
FP 201 Unit 2 - Part 3
 
Loops_in_Rv1.2b
Loops_in_Rv1.2bLoops_in_Rv1.2b
Loops_in_Rv1.2b
 
Lec 37 - pointers
Lec 37 -  pointersLec 37 -  pointers
Lec 37 - pointers
 
Pointers
PointersPointers
Pointers
 
4th_Ed_Ch03.pdf
4th_Ed_Ch03.pdf4th_Ed_Ch03.pdf
4th_Ed_Ch03.pdf
 
Lecturer23 pointersin c.ppt
Lecturer23 pointersin c.pptLecturer23 pointersin c.ppt
Lecturer23 pointersin c.ppt
 
Lec 38.39 - pointers
Lec 38.39 -  pointersLec 38.39 -  pointers
Lec 38.39 - pointers
 
Pointers in C
Pointers in CPointers in C
Pointers in C
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swift
 
Pointers in C
Pointers in CPointers in C
Pointers in C
 

En vedette (6)

No more Legacy documents
No more Legacy documentsNo more Legacy documents
No more Legacy documents
 
CIのその先へ
CIのその先へCIのその先へ
CIのその先へ
 
関数型言語のすすめ
関数型言語のすすめ関数型言語のすすめ
関数型言語のすすめ
 
Jenkins User Conference 2012 Tokyo 「SIerのJenkins事情」
Jenkins User Conference 2012 Tokyo 「SIerのJenkins事情」Jenkins User Conference 2012 Tokyo 「SIerのJenkins事情」
Jenkins User Conference 2012 Tokyo 「SIerのJenkins事情」
 
Lumen使ってみたレポ
Lumen使ってみたレポLumen使ってみたレポ
Lumen使ってみたレポ
 
Jenkins実践入門のnext step
Jenkins実践入門のnext stepJenkins実践入門のnext step
Jenkins実践入門のnext step
 

Similaire à yield and return (poor English ver)

Integral Calculus Anti Derivatives reviewer
Integral Calculus Anti Derivatives reviewerIntegral Calculus Anti Derivatives reviewer
Integral Calculus Anti Derivatives reviewer
JoshuaAgcopra
 
Functional Programming in F#
Functional Programming in F#Functional Programming in F#
Functional Programming in F#
Dmitri Nesteruk
 
High-Performance Haskell
High-Performance HaskellHigh-Performance Haskell
High-Performance Haskell
Johan Tibell
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
pramode_ce
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Mario Fusco
 
Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISP
Devnology
 

Similaire à yield and return (poor English ver) (20)

Monadologie
MonadologieMonadologie
Monadologie
 
Basic R Data Manipulation
Basic R Data ManipulationBasic R Data Manipulation
Basic R Data Manipulation
 
functions
functionsfunctions
functions
 
Matlab ch1 intro
Matlab ch1 introMatlab ch1 intro
Matlab ch1 intro
 
Integral Calculus Anti Derivatives reviewer
Integral Calculus Anti Derivatives reviewerIntegral Calculus Anti Derivatives reviewer
Integral Calculus Anti Derivatives reviewer
 
Functional Programming in F#
Functional Programming in F#Functional Programming in F#
Functional Programming in F#
 
Intro to Matlab programming
Intro to Matlab programmingIntro to Matlab programming
Intro to Matlab programming
 
High-Performance Haskell
High-Performance HaskellHigh-Performance Haskell
High-Performance Haskell
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
B61301007 matlab documentation
B61301007 matlab documentationB61301007 matlab documentation
B61301007 matlab documentation
 
Monads - Dublin Scala meetup
Monads - Dublin Scala meetupMonads - Dublin Scala meetup
Monads - Dublin Scala meetup
 
Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISP
 
Integration material
Integration material Integration material
Integration material
 
Integration
IntegrationIntegration
Integration
 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
 
01 - DAA - PPT.pptx
01 - DAA - PPT.pptx01 - DAA - PPT.pptx
01 - DAA - PPT.pptx
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
Flying Futures at the same sky can make the sun rise at midnight
Flying Futures at the same sky can make the sun rise at midnightFlying Futures at the same sky can make the sun rise at midnight
Flying Futures at the same sky can make the sun rise at midnight
 

Plus de bleis tift

Plus de bleis tift (20)

PCさえあればいい。
PCさえあればいい。PCさえあればいい。
PCさえあればいい。
 
F#の基礎(?)
F#の基礎(?)F#の基礎(?)
F#の基礎(?)
 
解説?FSharp.Quotations.Compiler
解説?FSharp.Quotations.Compiler解説?FSharp.Quotations.Compiler
解説?FSharp.Quotations.Compiler
 
効果の低いテストの話
効果の低いテストの話効果の低いテストの話
効果の低いテストの話
 
テストの自動化を考える前に
テストの自動化を考える前にテストの自動化を考える前に
テストの自動化を考える前に
 
札束でExcelを殴る
札束でExcelを殴る札束でExcelを殴る
札束でExcelを殴る
 
.NET系開発者から見たJava
.NET系開発者から見たJava.NET系開発者から見たJava
.NET系開発者から見たJava
 
SI屋のためのF# ~DSL編~
SI屋のためのF# ~DSL編~SI屋のためのF# ~DSL編~
SI屋のためのF# ~DSL編~
 
F#事例発表
F#事例発表F#事例発表
F#事例発表
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
 
F#の基礎(嘘)
F#の基礎(嘘)F#の基礎(嘘)
F#の基礎(嘘)
 
現実(えくせる)と戦う話
現実(えくせる)と戦う話現実(えくせる)と戦う話
現実(えくせる)と戦う話
 
ラムダでウィザード 滅せよ手続き、とチャーチは言った (※言ってません)
ラムダでウィザード 滅せよ手続き、とチャーチは言った (※言ってません)ラムダでウィザード 滅せよ手続き、とチャーチは言った (※言ってません)
ラムダでウィザード 滅せよ手続き、とチャーチは言った (※言ってません)
 
async/await不要論
async/await不要論async/await不要論
async/await不要論
 
F#によるFunctional Programming入門
F#によるFunctional Programming入門F#によるFunctional Programming入門
F#によるFunctional Programming入門
 
VBAを書きたくない話(Excel-DNAの紹介)
VBAを書きたくない話(Excel-DNAの紹介)VBAを書きたくない話(Excel-DNAの紹介)
VBAを書きたくない話(Excel-DNAの紹介)
 
Better C#の脱却を目指して
Better C#の脱却を目指してBetter C#の脱却を目指して
Better C#の脱却を目指して
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 
JSX / Haxe / TypeScript
JSX / Haxe / TypeScriptJSX / Haxe / TypeScript
JSX / Haxe / TypeScript
 
自分戦略
自分戦略自分戦略
自分戦略
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 

yield and return (poor English ver)

  • 1. yield and return ∼ Poor English ver. ∼ bleis-tift July 27, 2014
  • 3. Agenda Part1: Computation Expression Part2:Dierence of yield and return ∼considerations∼ Part3:Dierence of yield and return ∼implementations∼ Part4:Conclusion I will talk about how to implement computation expression.
  • 5. Computation expression is... expression that extends normal F# grammer and provides some customize points able to dene an user dene process . the grammer of F# .. . let someFunc a b = let x = f a let y = g b x + y . computation expression .. . let someFunc a b = builder { let! x = f a let! y = g b return x + y }
  • 6. Usages Remove nests of match expressions for option Hide parameters for state Remove nests of function call for async proc and so on... But I will skip these topics today.
  • 7. The way of implementation The computation exprs are implemented by some translation rules in F# Needless any interfaces Most important thing is which translated exprs are compilable . . grammer of computation expr translate normal grammer Let's look at some translation rules together!
  • 8. Notation Sans-Serif Code of F#. ex) fun x - x Serif meta Variables. ex) cexpr Itaric The part related to the translation. ex) T(e, C)
  • 9. Translation rule (most outside) . . builder-expr { cexpr } F#compiler translates following: . . let b = builder-expr in {| cexpr |} b is a fresh variable.
  • 10. builder-expr Just a normal expression Builder is evaluated only once Dene methods called at runtime into builder type All methods are dened as instance method
  • 11. {| ... |} Translate expr to core language grammer ex) {| cexpr |} ... translate cexpr See below for further detais
  • 12. cexpr The most outer target of translation Other computation expr is represented by ce cexpr is translated by Delay-trans, Quote-trans, Run-trans if necessary
  • 13. Representation of the translation rules The translation rules are described by T-notation . T-notation .. .T(e, C) e:The computation expr that will be translated C:The context that was translated Find the translation rule that match e, and translate it
  • 14. T-notation of {| cexpr |} . T-notation .. . {| cexpr |} ≡ T(cexpr, λv.v) λv.v is anonymous function before dot: the parameter after dot: the function body v is the translated expression Function application is done at compile-time (not run-time)
  • 15. Trans rule for return . Trans rule .. . T(return e, C) = C(b.Return(e)) if cexpr is return 42 then: . Example .. . T(return 42, λv.v) −→(λv.v)(b.Return(42)) −→b.Return(42) Complete!
  • 16. Trans rule for let . Trans rules .. . T(return e, C) = C(b.Return(e)) T(let p = e in ce, C) = T(ce, λv.C(let p = e in v)) . Example .. . 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. Trans rule of if . Trans rules .. . {| 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()) . Example .. . 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()
  • 18. Trans rule of ce1; ce2 . Trans rules .. . {| cexpr |} ≡ T(cexpr, λv.v) T(return e, C) = C(b.Return(e)) T(ce1; ce2, C) = C(b.Combine({| ce1 |},b.Delay(fun () - {| ce2 |}))) . Example .. . T(return 10; return 20, λv1.v1) −→(λv1.v1)(b.Combine({| return 10 |},b.Delay(fun () - {| return 20 |}))) −→(λv1.v1) (b.Combine(T(return 10, λv2.v2),b.Delay(fun () - T(return 20, λv3.v3)))) −→(λv1.v1) (b.Combine((λv2.v2)(b.Return(10)),b.Delay(fun () - (λv3.v3)(b.Return(20))))) −→(λv1.v1)(b.Combine(b.Return(10),b.Delay(fun () - b.Return(20)))) −→b.Combine(b.Return(10),b.Delay(fun () - b.Return(20)))
  • 19. Trans rule of while. Trans rules .. . {| cexpr |} ≡ T(cexpr, λv.v) T(return e, C) = C(b.Return(e)) T(if e then ce, C) = C(if e then {| ce |} else b.Zero()) T(ce1; ce2, C) = C(b.Combine({| ce1 |},b.Delay(fun () - {| ce2 |}))) T(while e do ce, C) = T(ce, λv.C(b.While(fun () - e,b.Delay(fun () - v)))) . Example .. . T (while f() do if g() then return 42 done; return 0, λv1.v1) −→(λv1.v1)(b.Combine({| while f() do if g() then return 42 |},b.Delay(fun () - {| return 0 |}))) −→(λv1.v1)(b.Combine( T (if g() then return 42, λv2.b.While(fun () - f(),b.Delay(fun () - v2))) ,b.Delay(fun () - b.Return(0)))) −→(λv1.v1)(b.Combine( (λv2.b.While(fun () - f(),b.Delay(fun () - v2)))(if g() then b.Return(42) else b.Zero()) ,b.Delay(fun () - b.Return(0)))) −→(λv1.v1)(b.Combine( b.While(fun () - f(),b.Delay(fun () - if g() then b.Return(42) else b.Zero())) ,b.Delay(fun () - b.Return(0)))) −→b.Combine(b.While(fun () - f(),b.Delay(fun () - if g() then b.Return(42) else b.Zero())) ,b.Delay(fun () - b.Return(0)))
  • 20. Feature of computation expr Computation expr is similar to do notation (Haskell) for expression (Scala) query expression (C#) Dierence is computation expr has more exibility than core language. Computation expr is more powerful and friendly!
  • 21. Part2:Dierence of yield and return ∼considerations∼
  • 22. Trans rules of yield and return . Trans rules .. . T(yield e, C) = C(b.Yield(e)) T(return e, C) = C(b.Return(e)) Dierent point is only method... Today's main theme: Why exist the same rules?
  • 23. Use properly...? use yield for yield-like and use return for return-like...? use yield for collection-like, otherwise uses return...? What's the xxx-like! I want to decide clearly.
  • 24. Thinking about dierence between yield and return Reer the dictionary: yield produce/provide return give back return should not be continue the following process. Monad's return? I don't know:)
  • 25. Dierence between yield and return . yield .. . list { yield 1 printfn done } .return .. . list { return 1 printfn done } Whether or not to print done
  • 26. The case of C return IET yield return yield break query expression select I want to realize something like yield return and yield break.
  • 27. seq expression return is not supported Dicult for yield break like C# Let's reimplements seq expression by computation expression!
  • 28. Part3:Dierence of yield and return ∼implementations∼
  • 29. Problem The trans rule is same yield and return...
  • 30. Plan 1 The focus on return breaks remained process Need to return value when called return Throw exception that wraps returning value in Return method and catch the exception in Run method
  • 31. Impl by exception . Builder .. . 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() // type function
  • 32. Impl by exception . Usage .. . seq2 { yield 1; yield 2 };; val it : seqint = seq [1; 2] seq2 { return 1; return 2 };; val it : seqint = seq [1] Yes!
  • 33. Impl by exception Scala uses exception for the part of implements return and break Looks like easy But!
  • 34. Problem . Bad Example .. . seq2 { yield 1; return 2; return 3 };; val it : seqint = seq [2] In C#: . C# .. . IEnumerableint F() { yield return 1; yield break 2; yield break 3; } It returns the sequencce contains 1 and 2.
  • 35. Rene version . Catch ReturnExn in Combine .. . 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()
  • 36. Impl by exception If provide try-with, need to catch ReturnExn in try-with and reraise it Eventually, can't implement clearly Disinclined for use to exception for control ow Could be realized at least
  • 37. Plan 2 Continue or not continue Insert the judgement of whether to call the rest process
  • 38. impl by state eld . Builder .. . 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. impl by state eld . Usage .. . 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] Yes!
  • 40. impl by state eld simple looks like easy But!
  • 41. Problem builder instance has state use the same builder instance at the same time... . . Thread A seq2 { yield 1 ; // Combine yield 2 // oops! } // Run val it : seqint = seq [1] seq2.isExit false true false Thread B seq2 { return 10 } // Run
  • 42. Rene version . Builder .. . type SeqBuilder() = (* ... *) let seq2 () = SeqBuilder() . Usage .. . 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]
  • 43. Impl by state eld Create the builder instance at every time Can't forbid that the user share the instance It's troublesome Does not stand for practical use...
  • 44. Plan 3 Problem: state sharing Solution: use the argument Carry the state by the argument, and unwrap the state in Run method The rest process is not called if the state is Break in Combine method
  • 45. Impl by state arg . Builder .. . 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. Impl by state arg . Usage .. . 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] Yes!
  • 47. Impl by state arg Symmetry of the return and yield became clear The implementation is very complex Looks like good.
  • 48. Comparison . Impl by exception .. . member this.Yield(x: 'T) = Seq.singleton x member this.Return(x: 'T) = raise (ReturnExn(Seq.singleton x)) . Impl by state eld .. . member this.Yield(x) = Seq.singleton x member this.Return(x) = isExit - true Seq.singleton x . Impl by state arg .. . member this.Yield(x) = Seq.singleton x, Continue member this.Return(x) = Seq.singleton x, Break
  • 49. Plan 4 Impl of exception: use the exception to break the rest process It is same to discard continuation yield: call continuation return: discard continuation
  • 50. Impl by continuation .Builder .. . 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() .Usage .. . 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]
  • 51. Impl by continuation Symmetry of return and yield is clear Shortest but complex (and not dene the Bind method) The state arg version too
  • 52. Speed Comparison Write yield at 100,000 times and execute. builder time unsupported return 20.5ms by exception 20.5ms by state eld 20.7ms by state arg 21.2ms by continuation 22.6ms seq expr 1.18ms The dierence is less. But builer is slower than seq expr in the rst place.
  • 54. Summary The computation expression is powerful yield and return have the same translation rule but the meaning is dierent The seq expression is not supported return → reimplementation Implementations: by exception by state eld (deprecated) by state arg by continuation
  • 55. Impl status of some libraries Design about return ex) seq/list/option Target libraries: FSharpx ExtCore FSharpPlus Basis.Core As of July 21, 2014
  • 56. Impl status of some libraries . Benchmark code .. . 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 } Can compile it It returns false-like value
  • 57. Impl status of some libraries . Expanded benchmark code .. . 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)))))
  • 59. FSharpx The type of Combine is bad. . Signature of Combine .. .'a option * ('a - 'b option) - 'b option . Expand of error point .. . // 'a option * ('a - 'b option) - 'b option b.Combine( // bool option (if xs.[!i] = -1 then b.Return(false) else b.Zero()), // unit - 'a option b.Delay(fun () - incr i; b.Zero())) . Correct signature .. .'a option * (unit - 'a option) - 'a option
  • 61. ExtCore The impl of Zero is bad. . Implementation of Zero .. . member inline __.Zero () : unit option = Some () // TODO : Should this be None? comment...
  • 64. Impl status of some libraries No Game!
  • 65. Rethink about dierence yield and return Very few libraries implement computation expr correctly There is a problem to be solved before yield and return Should we give a semantic dierence really? Should give if you want to take advantage of computation expr Should not give if you provide only Bind and Return (like FSharpPlus)
  • 66. Rethink about computation expression Should Yield and Return receive continuation? Compile-time translation is ecient Can implement yield and return by now rules I want to take this exibility
  • 67. Suggestion of a Policy The considered separately depending on the library design Case 1: provide monad/monad plus Case 2: provide more general computing Case 3: use computaion expr other than monad
  • 68. Provide monad/monad plus Provide monad Required: Bind/Return Optional: ReturnFrom (for convinience) Optional: Run Provide another builder that unwrap the value Provide monad plus Required: Bind/Return/Zero/Combine Zero is mzero, Combine is mplus Required: Delay (depends on trans rule of Combine) member this.Delay(f) = f ()
  • 69. Provide more general computing Separate the modules by feature Builder module for providing Bind/Return Builder module for providing Bind/Return/Comine Combine is not mplus. Combine + Delay is mplus. Inevitably, required Delay/Run member this.Delay(f) = f member this.Run(f) = f () Optional: Zero Support if-expr without else-clause
  • 70. Use computaion expr other than monad I have no comments:) If provide Combine, think about yield and return Use CustomOperation if necessary
  • 71. Tasks Report the bug to FSharpx and ExtCore Create a library that is divided the module by feature Verify builder Edication