Upload
others
View
10
Download
0
Embed Size (px)
Citation preview
Dependently Typed Functional Programming withIdris
Lecture 2: Embedded Domain Specific Languages
Edwin BradyUniversity of St Andrews
@edwinbrady
Introduction
In this lecture:
Some history
Programming Languages and Abstraction
A well-typed interpreter
Embedding languages with syntax overloading
OS interaction and foreign functions
Managing resources
Abstraction
Computer Scientists often talk of abstraction
English definition: “the process of considering somethingindependently of its associations or attributes”
In Computer Science:
“. . . a process of extracting the general structure to allow theinessential details to be ignored”— Ron Morrison, PhD ThesisSeparation of what a program or system does from how
We can view a computer system as a number of layers ofabstraction
Abstraction
Computer Scientists often talk of abstraction
English definition: “the process of considering somethingindependently of its associations or attributes”
In Computer Science:
“. . . a process of extracting the general structure to allow theinessential details to be ignored”— Ron Morrison, PhD ThesisSeparation of what a program or system does from how
We can view a computer system as a number of layers ofabstraction
Some History
1946 — ENIAC, the first general purpose electronic computer
Turing Complete — meaning it could run any computablefunction
But. . . no abstraction!
Programmed by manipulating switches and cables on themachine
Some History
1949 — EDSAC, the first practical stored program computer
Programs stored in memory as binary data
1950 (approx) — Assembly Language
Mnemonics for machine instructionsMOV A, R4
ADD B, R4
MOV R4, C
HALT
New abstraction: human readable notation for machinelanguage
Some History
1949 — EDSAC, the first practical stored program computer
Programs stored in memory as binary data
1950 (approx) — Assembly Language
Mnemonics for machine instructionsMOV A, R4
ADD B, R4
MOV R4, C
HALT
New abstraction: human readable notation for machinelanguage
Some History
1952 — A-0, the first compiler
“Arithmetic Language version 0”
Converted a specification into machine code
Created by Grace Hopper
“She did this, she said, because she was lazy and hoped that theprogrammer may return to being a mathematician.”(http://www.sdsc.edu/ScienceWomen/hopper.html)
Some History
1952 — A-0, the first compiler
“Arithmetic Language version 0”
Converted a specification into machine code
Created by Grace Hopper
“She did this, she said, because she was lazy and hoped that theprogrammer may return to being a mathematician.”(http://www.sdsc.edu/ScienceWomen/hopper.html)
Some History
1957 — FORTRAN (FORmula TRANslator)
Intended as a more practical alternative to hand-writingassembly language
Invented by a team led by John Backus
New abstraction: Familiar mathematical notation
C = A + B
“Much of my work has come from being lazy. I didn’t like writingprograms, and so, when I was working on the IBM 701, writingprograms for computing missile trajectories, I started work on aprogramming system to make it easier to write programs.”— John Backus
Some History
1957 — FORTRAN (FORmula TRANslator)
Intended as a more practical alternative to hand-writingassembly language
Invented by a team led by John Backus
New abstraction: Familiar mathematical notation
C = A + B
“Much of my work has come from being lazy. I didn’t like writingprograms, and so, when I was working on the IBM 701, writingprograms for computing missile trajectories, I started work on aprogramming system to make it easier to write programs.”— John Backus
High Level Languages
Since FORTRAN, many new high level languages have beendesigned — providing new abstractions, targetting new applicationdomains. A selection:
LISP (1958), ALGOL (1960), C (1973), ML (1973), C++(1983), Haskell (1990), Java (1995), Go (2009)
“ Most programming languages are partly a way of expressingthings in terms of other things and partly a basic set of giventhings.”
— Peter Landin, “The next 700 programming languages” (1966)
High Level Languages
Since FORTRAN, many new high level languages have beendesigned — providing new abstractions, targetting new applicationdomains. A selection:
LISP (1958), ALGOL (1960), C (1973), ML (1973), C++(1983), Haskell (1990), Java (1995), Go (2009)
“ Most programming languages are partly a way of expressingthings in terms of other things and partly a basic set of giventhings.”
— Peter Landin, “The next 700 programming languages” (1966)
Domain Specific Languages
A Domain Specific Language (DSL) is a language designed fora particular problem domain
Very high level of abstractionTypically declarative, i.e. say what, not howOften not Turing Complete
Examples:
Database and Internet applications — HTML, XML, SQL, . . .Scientific programming — R, MathematicaComputer games — UnrealScriptHardware description — VerilogSpreadsheet formulas
Domain Specific Languages
A Domain Specific Language (DSL) is a language designed fora particular problem domain
Very high level of abstractionTypically declarative, i.e. say what, not howOften not Turing Complete
Email filtering:
Domain Specific Languages
A Domain Specific Language (DSL) is a language designed fora particular problem domain
Very high level of abstractionTypically declarative, i.e. say what, not howOften not Turing Complete
Music playlists
DSLs in Idris
Idris aims to support the implementation of verified domainspecific languages. To illustrate this, we begin with an interpreterfor the simply typed λ-calculus.
First Attempt
Expressions
data Expr = Val Int
| Add Expr Expr
Evaluator
interp : Expr -> Int
interp (Val x) = x
interp (Add l r) = interp l + interp r
First Attempt
Expressions
data Expr = Val Int
| Add Expr Expr
Evaluator
interp : Expr -> Int
interp (Val x) = x
interp (Add l r) = interp l + interp r
First Attempt
Expressions
data Expr = Val Int
| Var String
| Add Expr Expr
Evaluator
interp : List (String, Int) -> Expr -> Maybe Int
interp env (Val x) = x
interp env (Var n) = case lookup n env of
Nothing => Nothing
Just val => val
interp env (Add l r) = interp env l + interp env r
First Attempt
Expressions
data Expr = Val Int
| Var String
| Add Expr Expr
Evaluator
interp : List (String, Int) -> Expr -> Maybe Int
interp env (Val x) = x
interp env (Var n) = case lookup n env of
Nothing => Nothing
Just val => val
interp env (Add l r) = interp env l + interp env r
Preliminaries
Types
data Ty = TyInt
| TyBool
| TyFun Ty Ty
Interpreting types
interpTy : Ty -> Type
interpTy TyInt = Int
interpTy TyBool = Bool
interpTy (TyFun s t) = interpTy s -> interpTy t
Preliminaries
Types
data Ty = TyInt
| TyBool
| TyFun Ty Ty
Interpreting types
interpTy : Ty -> Type
interpTy TyInt = Int
interpTy TyBool = Bool
interpTy (TyFun s t) = interpTy s -> interpTy t
Preliminaries
The Finite Sets
data Fin : Nat -> Type where
fO : Fin (S k)
fS : Fin k -> Fin (S k)
Example: Bounds Safe Vector Lookup
total
index : Fin n -> Vect a n -> a
index fO (x::xs) = x
index (fS k) (x::xs) = index k xs
Preliminaries
The Finite Sets
data Fin : Nat -> Type where
fO : Fin (S k)
fS : Fin k -> Fin (S k)
Example: Bounds Safe Vector Lookup
total
index : Fin n -> Vect a n -> a
index fO (x::xs) = x
index (fS k) (x::xs) = index k xs
Preliminaries
We can represent variables as a de Bruijn index
Nameless
A number, counting binders since the variable was bound
λxy .x + y =⇒ λxy .1 + 0
If there are n variables:
Fin n represents a bounded de Bruijn indexindex i G is a bounds safe lookup of variable i in context G.
Preliminaries
We can represent variables as a de Bruijn index
Nameless
A number, counting binders since the variable was bound
λxy .x + y =⇒ λxy .1 + 0
If there are n variables:
Fin n represents a bounded de Bruijn indexindex i G is a bounds safe lookup of variable i in context G.
Preliminaries
Environments
using (G : Vect Ty n)
data Env : Vect Ty n -> Type where
Nil : Env Nil
(::) : interpTy a -> Env G -> Env (a :: G)
data HasType : (i : Fin n) -> Vect Ty n -> Ty ->
Type where
stop : HasType fO (t :: G) t
pop : HasType k G t ->
HasType (fS k) (u :: G) t
Preliminaries
Environment Example
ctxt : Vect Ty (S (S O))
ctxt = [TyInt, TyBool]
env : Env ctxt
env = [42, True]
isBool : HasType (fS fO) ctxt TyBool
isBool = pop stop
Syntax Overloading
dsl notation
dsl expr
lambda = Lam
variable = Var
index_first = stop
index_next = pop
Syntax Overloading
syntax rules
syntax IF [x] THEN [t] ELSE [e] = If x t e
forLoop : List a -> (a -> IO ()) -> IO ()
syntax for {x} "in" [xs] ":" [body]
= forLoop xs (\x => body)
Syntax Overloading
Implicit conversions
data Lang : Vect Ty n -> Ty -> Type where
Val : interpTy a -> Lang G a
...
implicit MkVal : interpTy a -> Lang G a
MkVal = Val
Interlude: Foreign Function Calls
Foreign Types
data FTy = FInt | FFloat | FChar | FString
| FPtr | FAny Type | FUnit
Foreign Types to Idris
interpFTy : FTy -> Type
interpFTy FInt = Int
interpFTy FFloat = Float
interpFTy FChar = Char
interpFTy FString = String
interpFTy FPtr = Ptr
interpFTy (FAny t) = t
interpFTy FUnit = ()
Interlude: Foreign Function Calls
Foreign Types
data FTy = FInt | FFloat | FChar | FString
| FPtr | FAny Type | FUnit
Foreign Types to Idris
interpFTy : FTy -> Type
interpFTy FInt = Int
interpFTy FFloat = Float
interpFTy FChar = Char
interpFTy FString = String
interpFTy FPtr = Ptr
interpFTy (FAny t) = t
interpFTy FUnit = ()
Interlude: Foreign Function Calls
Building Foreign Function Calls
ForeignTy : (xs:List FTy) -> (t:FTy) -> Type
data Foreign : Type -> Type where
FFun : String -> (xs:List FTy) -> (t:FTy) ->
Foreign (ForeignTy xs t)
mkForeign : Foreign x -> x
Interlude: Foreign Function Calls
Examples
putStr : String -> IO ()
putStr x
= mkForeign (FFun "putStr" [FString] FUnit) x
getChar : IO Char
getChar = mkForeign (FFun "getchar" [] FChar)
Interlude: Foreign Function Calls
Examples
data File = FHandler Ptr
do_fopen : String -> String -> IO Ptr
do_fopen f m
= mkForeign
(FFun "fileOpen" [FString, FString] FPtr) f m
openFile : String -> Mode -> IO File
openFile f m = fopen f (modeStr m) where
modeStr Read = "r"
modeStr Write = "w"
modeStr ReadWrite = "r+"
Extra-functional Correctness
“Nobody in industry really cares whether a program does what it’ssupposed to – what they are really concerned with is how theprogram behaves when it’s run.”
— Joe Armstrong (designer of Erlang programming language)
Extra-functional Correctness
We make a distinction between:
Functional correctness
Does the program do what it is supposed to do?e.g. Does sort produce an ordered permutation of its input?
Extra-functional correctness
Does the program run within the required resource constraints?e.g. Does the program run within 1 Mb RAM? Does it respondto input within 1 second?
Resource Example: Files
A program which manages files must conform to a resource usageprotocol. Informally:
Files must be opened succesfully before they are read orwritten
A file open for reading may not be written to, and vice versa
Files must be closed when processing is finished
We have developed a domain specific language for encoding, ingeneral, resource usage protocols