language oriented programming in f# robert pickering, chance coble, roger castillo
TRANSCRIPT
Language Oriented Programming in F#
Robert Pickering, Chance Coble, Roger Castillo
Languages are Logic
• Programming languages provide a way to express logic in a symbolic notation
• Combinators give us a way to express logic
• Using this approach we can create a few atoms, many rewrite rules and presto…New Language
Combinators
true-fn(x, y) = xfalse-fn(x, y) = yor-fn(x, y) = x(true-fn, y)and-fn(x, y) = x(y, false-fn)
or x y x=true-fn x=false-fn
y=true-fn true-fn true-fn
y=false-fn true-fn false-fn
Combinators
true-fn(x, y) = xfalse-fn(x, y) = yor-fn(x, y) = x(true-fn, y)and-fn(x, y) = x(y, false-fn)not-fn (a(x,y)) = a(y,x)equals-fn x y = x(y, (not-fn y))Implication-fn x y = or((not-fn x), y)
Combinators
true-fn(x, y) = xfalse-fn(x, y) = yor-fn(x, y) = x(true-fn, y)and-fn(x, y) = x(y, false-fn)not-fn( a (x, y)) = a(y, x)equals-fn(x, y) = x(y, (not-fn y))implication-fn(x, y) = or((not-fn x),
y)
and-fn(x, y) = not-fn (or-fn ((not-fn x), (not-fn y))= not-fn ((not-fn x)(true-fn, (not-fn y)))= not-fn (x (false-fn, y))= x(y, false-fn)
While Statement
while (true) { if (1!=1) Console.WriteLine(“Cosmic Death Ray
Detected”);}
Statement Grammer
if
statement list
Boolean expression
while (true) { if (1!=1) Console.WriteLine(“Cosmic Death Ray Detected”);}
Statements and Expressions
if
statement list
Boolean expression
while
statement list
Boolean expression
while (true) { if (1!=1) Console.WriteLine(“Cosmic Death Ray Detected”);}
Syntax Tree
while (true) { if (1!=1) Console.WriteLine(“Cosmic Death Ray Detected”);}
if
statement list
Boolean expression
while
Boolean expression
(1!=1)
(true)
Abstract Syntax Tree
This language is a list of statementsThe statements must follow a
grammar that can be represented by a tree
if
statement list
Boolean expression
while
Boolean expression
Abstract Syntax Trees and Grammars
This language is a list of statementsThe statements must follow a grammar
that can be represented by BNF
statement ::= ‘while’ ‘(‘expression’)’ statement-list
| ‘if’ ‘(‘expression’)’ statement-list
| ... | ...
Direct Translation From Grammar
statement ::= ‘while’ ‘(‘expression’)’ statement-list
| ‘if’ ‘(‘expression’)’ statement-list | ... | ...
// F# Discriminated Uniontype Statement = | While of bool expression * Statement list | If of bool expression * Statement list
Abstract Syntax Tree
type Statement = | While of bool expression * Statement
list | If of bool expression * Statement list
Tuple Syntax (X,Y)
Union Types – The Option Type
// The pre-defined option typetype Option<'a> = | Some of 'a | None
// constructing optionslet someValue = Some 1let noValue = None
// pattern matching over optionslet convert value = match value with | Some x -> Printf.sprintf "Value: %i" x | None -> "No value"
Union Types - Trees// a binary tree definitiontype BinaryTree<'a> = | Node of BinaryTree<'a> * BinaryTree<'a> | Leaf of 'a
// walk the tree collection valueslet rec collectValues acc tree = match tree with | Node(ltree, rtree) -> // recursively walk the left tree let acc = collectValues acc ltree // recursively walk the right tree collectValues acc rtree | Leaf value -> value :: acc // add value to accumulator
Using the Tree
// define a treelet tree = Node( Node(Leaf 1, Leaf 2), Node(Leaf 3, Leaf 4))
// recover all values from the leaveslet values = collectValues [] tree
Union Types – Multiple Patterns
// balance the left side of the treelet balanceLeft tree = match tree with | RedTree (y, yv, RedTree(x, xv, a, b), c) -> RedTree(y, yv, BlackTree(x, xv, a, b), c) | RedTree (x, xv, a, RedTree(y, yv, b, c)) -> // none matched, just make a tree RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d)) | _ -> mkTree(isBlack, z, zv, l, d) // none matched, just make a tree
Can we do this using other constructs?
• Enum• Inheritance
OO
Functional
Types
Operations
Performance in Ticks / Invocation
type Prop = | Line of Point list * (TimedIndex -> Point) * MaterialColor | Surface of Origin * SurfaceProperties * (TimedPoint ->
float) | Triangle of (int -> TriangleFace) | TextAnnotation of (int -> RectangleFace * string) | Sphere of SphereProperties | Cylinder of CylinderProperties
type Scene = | AnimatedScene of Prop list * Scene * SceneSpeed | StillScene of Prop list * Scene | Empty
3D Visualization DSL
Demo
let rec eval model = function | AnimatedScene(ps,scene,speed) -> // … skipping some timer code let model' = fold evalProp model ps // … eval model' scene | Empty -> model
Evaluating the Language
let evalProp env prop = match prop with | Line(points,updateFunction,thickness,color) -> let l = evalLine
points updateFunction thickness color
env.View.Children.Add(l)
env | Triangle(f) -> evalTriangle f
env | TextAnnotation(rectUpdate,opacity) -> evalAnnotation
rectUpdate opacity
env | Sphere props -> env.View.Children.Add (evalSphere props) env | Cylinder props -> env.View.Children.Add (evalCylinder props) env
Production Rules
Wrap up
• Combinator libraries offer compositional thinking
• Increased modularity in operations (as opposed to objects)
• Reasoning by substitution