AFunc'onalIntroduc'on
COS326DavidWalker
PrincetonUniversityslidescopyright2013-2015DavidWalkerandAndrewW.Appel
permissiongrantedtoreusetheseslidesfornon-commercialeduca'onalpurposes
ThinkingFunc'onallyInJavaorC,youget(most)workdonebychangingsomethingInML,youget(most)workdonebyproducingsomethingnew
temp=pair.x;pair.x=pair.y;pair.y=temp; commandsmodifyorchangean
exis'ngdatastructure(likepair)
let(x,y)=pairin(y,x)
youanalyzeexis'ngdata(likepair)andyouproducenewdata(y,x)
2
Thissimpleswitchinperspec'vecanchangethewayyouthink
aboutprogrammingandproblemsolving.
3
ThinkingFunc'onally
impera'vecode:• outputsareirrelevant!• outputisnotfunc9onofinput• vola9le• unrepeatable• parallelismhidden• hardertotest• hardertocompose
pure,func'onalcode:• outputsareeverything!• outputisfunc9onofinput• persistent• repeatable• parallelismapparent• easiertotest• easiertocompose
temp=pair.x;pair.x=pair.y;pair.y=temp;
let(x,y)=pairin(y,x)
4
WhyOCaml?5
Small,orthogonalcorebasedonthelambdacalculus.– Controlisbasedon(recursive)func'ons.– Insteadoffor-loops,while-loops,do-loops,iterators,etc.
• canbedefinedaslibraryfunc'ons.– Makesiteasytodefineseman'cs
Supportsfirst-class,lexically-scoped,higher-orderprocedures– a.k.a.first-classfunc'onsorclosuresorlambdas.– first-class:func'onsaredatavalueslikeanyotherdatavalue
• likenumbers,theycanbestored,definedanonymously,...– lexically-scoped:meaningofvariablesdeterminedsta'cally.– higher-order:func'onsasargumentsandresults
• programspassedtoprograms;generatedfromprograms
ThesefeaturesalsofoundinRacket,Haskell,SML,F#,Clojure,....
WhyOCaml?6
Sta'callytyped:debuggingandtes'ngaid– compilercatchesmanysillyerrorsbeforeyoucanrunthecode.
• Atypeisworthathousandtests(startat6:20):– h]ps://www.youtube.com/watch?v=q1Yi-WM7XqQ
– Javaisalsostrongly,sta'callytyped.– Scheme,Python,Javascript,etc.areallstrongly,dynamicallytyped–typeerrorsarediscoveredwhilethecodeisrunning.
Stronglytyped:compilerenforcestypeabstrac'on.– cannotcastanintegertoarecord,func'on,string,etc.
• sowecanu'lizetypesascapabili9es;crucialforlocalreasoning– C/C++areweakly-typed(sta'callytyped)languages.Thecompilerwillhappilyletyoudosomethingsmart(moreo?enstupid).
Typeinference:compilerfillsintypesforyou
Installing,runningOcaml7
• OCamlcomeswithcompilers:– “ocamlc”–fastbytecodecompiler– “ocamlopt”–op'mizing,na'vecodecompiler– “ocamlbuild–anicewrapperthatcomputesdependencies
• Andaninterac've,top-levelshell:– occasionallyusefulfortryingsomethingout.– “ocaml”attheprompt.
• Andmanyothertools– e.g.,debugger,dependencygenerator,profiler,etc.
• Seethecoursewebpagesforinstalla'onpointers– alsoOCaml.org
Edi'ngOcamlPrograms8
• Manyop'ons:pickyourownpoison– Emacs
• whatI’llbeusinginclass.• goodbutnotgreatsupportforOCaml.• ontheotherhand,it’ss'llthebestcodeeditorI’veused
– thatmaybebecauseI'moldandstuckinmyways:-)• (extensionswri]eninelisp–afunc'onallanguage!)
– OCamlIDE• integrateddevelopmentenvironmentwri]eninOcaml.• haven’tuseditmuch,socan’tcomment.
– Eclipse• I’veputupalinktoanOcamlplugin• Ihaven'ttrieditbutothersrecommendit
– Sublime• Alotofstudentsseemtogravitatetothis
XKCDonEditors
9
ANINTRODUCTORYEXAMPLE(ORTWO)
10
OCamlCompilerandInterpreter• Demo:
– emacs– mlfiles– wri'ngsimpleprograms:hello.ml,sum.ml– simpledebuggingandunittests– ocamlccompiler
11
AFirstOCamlProgram
hello.ml:
print_string “Hello COS 326!!\n";;
12
print_string “Hello COS 326!!\n";;
AFirstOCamlProgram
hello.ml:
afunc'on itsstringargumentenclosedin"..."
top-levelexpressionsterminatedby;;
13
AFirstOCamlProgram
print_string “Hello COS 326!!\n";;
$ ocamlbuild hello.d.byte $ ./hello.d.byte Hello COS 326!! $
hello.ml:
compiling and running hello.ml:
.dfordebugging(otherchoices.pforprofiled;ornone)
.byteforinterpretedbytecode(otherchoices.na'veformachinecode)
14
AFirstOCamlProgram
$ ocaml Objective Caml Version 3.12.0
#
hello.ml:
interpreting and playing with hello.ml:
print_string “Hello COS 326!!\n";;
15
AFirstOCamlProgram
$ ocaml Objective Caml Version 3.12.0
# 3 + 1;; - : int = 4 #
hello.ml:
interpreting and playing with hello.ml:
print_string “Hello COS 326!!\n";;
16
AFirstOCamlProgram
$ ocaml Objective Caml Version 3.12.0
# 3 + 1;; - : int = 4 # #use "hello.ml";; hello cos326!! - : unit = () #
hello.ml:
interpreting and playing with hello.ml:
print_string “Hello COS 326!!\n";;
17
AFirstOCamlProgram
$ ocaml Objective Caml Version 3.12.0
# 3 + 1;; - : int = 4 # #use "hello.ml";; hello cos326!! - : unit = () # #quit;; $
hello.ml:
interpreting and playing with hello.ml:
print_string “Hello COS 326!!\n";;
18
ASecondOCamlProgram
(* sum the numbers from 0 to n precondition: n must be a natural number *) let rec sumTo (n:int) : int = match n with 0 -> 0 | n -> n + sumTo (n-1) ;; print_int (sumTo 8);; print_newline();;
acomment(*...*)sumTo8.ml:
19
(* sum the numbers from 0 to n precondition: n must be a natural number *) let rec sumTo (n:int) : int = match n with 0 -> 0 | n -> n + sumTo (n-1) ;; print_int (sumTo 8);; print_newline();;
ASecondOCamlProgram
thenameofthefunc'onbeingdefined
thekeyword“let”beginsadefini'onthekeyword“rec”indicatesthedefini'onisrecursive
top-leveldeclara'onendswith“;;”
sumTo8.ml:
20
(* sum the numbers from 0 to n precondition: n must be a natural number *) let rec sumTo (n:int) : int = match n with 0 -> 0 | n -> n + sumTo (n-1) ;; print_int (sumTo 8);; print_newline();;
ASecondOCamlProgram
resulttypeint
argumentnamednwithtypeint
sumTo8.ml:
21
(* sum the numbers from 0 to n precondition: n must be a natural number *) let rec sumTo (n:int) : int = match n with 0 -> 0 | n -> n + sumTo (n-1) ;; print_int (sumTo 8);; print_newline();;
ASecondOCamlProgram
deconstructthevaluenusingpa]ernmatching
datatobedeconstructedappearsbetweenkeywords“match”and“with”
sumTo8.ml:
22
(* sum the numbers from 0 to n precondition: n must be a natural number *) let rec sumTo (n:int) : int = match n with 0 -> 0 | n -> n + sumTo (n-1) ;; print_int (sumTo 8);; print_newline();;
ASecondOCamlProgram
deconstructeddatamatchesoneof2cases:(i)thedatamatchesthepa]ern0,or(ii)thedatamatchesthevariablepa]ernn
ver'calbar"|"separatesthealterna'vepa]erns
sumTo8.ml:
23
(* sum the numbers from 0 to n precondition: n must be a natural number *) let rec sumTo (n:int) : int = match n with 0 -> 0 | n -> n + sumTo (n-1) ;; print_int (sumTo 8);; print_newline();;
ASecondOCamlProgram
Eachbranchofthematchstatementconstructsaresult
constructtheresult0
constructaresultusingarecursivecalltosumTo
sumTo8.ml:
24
(* sum the numbers from 0 to n precondition: n must be a natural number *) let rec sumTo (n:int) : int = match n with 0 -> 0 | n -> n + sumTo (n-1) ;; print_int (sumTo 8);; print_newline();;
ASecondOCamlProgram
printtheresultofcallingsumToon8
printanewline
sumTo8.ml:
25
OCAMLBASICS:EXPRESSIONS,VALUES,SIMPLETYPES
26
Expressions,Values,Types• Expressionsarecomputa'ons
– 2+3isacomputa'on
• Valuesaretheresultsofcomputa'ons– 5isavalue
• Typesdescribecollec'onsofvaluesandthecomputa'onsthatgeneratethosevalues– intisatype
– valuesoftypeintinclude• 0,1,2,3,…,max_int• -1,-2,…,min_int
27
Moresimpletypes,values,opera'ons28
Type: Values: Expressions:int -2, 0, 42 42 * (13 + 1) float 3.14, -1., 2e12 (3.14 +. 12.0) *. 10e6
char ’a’, ’b’, ’&’ int_of_char ’a’
string "moo", "cow" "moo" ^ "cow" bool true, false if true then 3 else 4
unit () print_int 3
Formoreprimi'vetypesandfunc'onsoverthem,seetheOCamlReferenceManualhere:
h]p://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html
Noteveryexpressionhasavalue29
Expression:42 * (13 + 1) evaluates to 588 (3.14 +. 12.0) *. 10e6 ↦ 151400000.
int_of_char ’a’ ↦ 97
"moo" ^ "cow" ↦ “moocow" if true then 3 else 4 ↦ 3 print_int 3 ↦ ()
1 + "hello" does not evaluate!
LanguageDefini'on• Thereareanumberofwaystodefineaprogramminglanguage• Inthisclass,wewillbrieflyinves'gate:
– Syntax– Evalua'on– Typechecking
• StandardML,averycloserela'veofOCaml,hasafulldefini'onofeachofthesepartsandanumberofproofsofcorrectness– Formoreonthistheme,seeCOS441/510
• TheOCamlManualfleshesoutthesyntax,evalua'onandtypecheckingrulesinformally
30
OCAMLBASICS:COREEXPRESSIONSYNTAX
31
CoreExpressionSyntax32
ThesimplestOCamlexpressionseare:• values numbers,strings,bools,...• id variables(x,foo,...)• e1ope2 operators(x+3,...)• ide1e2…en func9oncall(foo342)• letid=e1ine2 localvariabledecl.• ife1thene2elsee3 acondi9onal• (e) aparenthesizedexpression• (e:t) anexpressionwithitstype
Anoteonparentheses33
Inmostlanguages,argumentsareparenthesized&separatedbycommas: f(x,y,z) sum(3,4,5)
InOCaml,wedon’twritetheparenthesesorthecommas:
f x y z sum 3 4 5
Butwedohavetoworryaboutgrouping.Forexample, f x y z f x (y z)
Thefirstonepassesthreeargumentstof(x,y,andz)Thesecondpassestwoargumentstof(x,andtheresultofapplyingthe
func'onytoz.)
OCAMLBASICS:TYPECHECKING
34
TypeChecking• Everyvaluehasatypeandsodoeseveryexpression• ThisisaconceptthatisfamiliarfromJavabutitbecomes
moreimportantwhenprogramminginafunc'onallanguage• Thetypeofanexpressionisdeterminedbythetypeofits
subexpressions• Wewrite(e:t)tosaythatexpressionehastypet.eg:
2:int "hello":string2+2:int "Isay"^"hello":string
35
TypeCheckingRules• Thereareasetofsimplerulesthatgoverntypechecking
– programsthatdonotfollowtheruleswillnottypecheckandO’Camlwillrefusetocompilethemforyou(thenerve!)
– atfirstyoumayfindthistobeapain…
• Buttypesareagreatthing:– theyhelpusthinkabouthowtoconstructourprograms– theyhelpusfindstupidprogrammingerrors– theyhelpustrackdowncompa'bilityerrorsquicklywhenweeditandmaintainourcode
– theyallowustoenforcepowerfulinvariantsaboutourdatastructures
36
TypeCheckingRules• Examplerules:
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
37
TypeCheckingRules• Examplerules:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3) (4)
38
TypeCheckingRules• Examplerules:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
39
TypeCheckingRules• Examplerules:
• Usingtherules:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
2:intand3:int. (Byrule1)
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
40
TypeCheckingRules• Examplerules:
• Usingtherules:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
2:intand3:int. (Byrule1)Therefore,(2+3):int (Byrule3)
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
41
TypeCheckingRules• Examplerules:
• Usingtherules:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
2:intand3:int. (Byrule1)Therefore,(2+3):int (Byrule3)5:int (Byrule1)
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
42
TypeCheckingRules• Examplerules:
• Usingtherules:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
2:intand3:int. (Byrule1)Therefore,(2+3):int (Byrule3)5:int (Byrule1)Therefore,(2+3)*5:int (Byrule4andourpreviouswork)
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
FYI:Thisisaformalproofthattheexpressioniswell-
typed!
43
TypeCheckingRules• Examplerules:
• Anotherperspec've:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
????*????:int
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
rule(4)fortypingexpressionssaysIcanputanyexpressionwithtypeintinplaceofthe????
44
TypeCheckingRules• Examplerules:
• Anotherperspec've:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
7*????:int
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
rule(4)fortypingexpressionssaysIcanputanyexpressionwithtypeintinplaceofthe????
45
TypeCheckingRules• Examplerules:
• Anotherperspec've:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
7*(add_one17):int
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
rule(4)fortypingexpressionssaysIcanputanyexpressionwithtypeintinplaceofthe????
46
TypeCheckingRules• YoucanalwaysstartuptheOCamlinterpretertofindouta
typeofasimpleexpression:
$ ocaml Objective Caml Version 3.12.0
#
47
TypeCheckingRules• YoucanalwaysstartuptheOCamlinterpretertofindouta
typeofasimpleexpression:
$ ocaml Objective Caml Version 3.12.0
# 3 + 1;;
48
TypeCheckingRules• YoucanalwaysstartuptheOCamlinterpretertofindouta
typeofasimpleexpression:
$ ocaml Objective Caml Version 3.12.0
# 3 + 1;; - : int = 4 #
pressreturnandyoufindoutthetypeandthevalue
49
TypeCheckingRules• YoucanalwaysstartuptheOCamlinterpretertofindouta
typeofasimpleexpression:
$ ocaml Objective Caml Version 3.12.0
# 3 + 1;; - : int = 4 # “hello ” ^ “world”;; - : string = “hello world” #
pressreturnandyoufindoutthetypeandthevalue
50
TypeCheckingRules• YoucanalwaysstartuptheOCamlinterpretertofindouta
typeofasimpleexpression:
$ ocaml Objective Caml Version 3.12.0
# 3 + 1;; - : int = 4 # “hello ” ^ “world”;; - : string = “hello world” # #quit;; $
51
TypeCheckingRules• Examplerules:
• Viola'ngtherules:
ife1:intande2:intthene1+e2:int
ife1:intande2:intthene1*e2:int
ife1:stringande2:stringthene1^e2:string
ife:intthenstring_of_inte:string
"hello":string (Byrule2)1:int (Byrule1)1+"hello":?? (NOTYPE!Rule3doesnotapply!)
0:int (andsimilarlyforanyotherintegerconstantn)
"abc":string (andsimilarlyforanyotherstringconstant"…")(2)
(1)
(3)
(5)
(4)
(6)
52
• Viola'ngtherules:
• Thetypeerrormessagetellsyouthetypethatwasexpectedandthetypethatitinferredforyoursubexpression
• Bytheway,thiswasoneofthenonsensicalexpressionsthatdidnotevaluatetoavalue
• Itisagoodthingthatthisexpressiondoesnottypecheck!“Welltypedprogramsdonotgowrong”
RobinMilner,1978
TypeCheckingRules• Viola'ngtherules:
• Thetypeerrormessagetellsyouthetypethatwasexpectedandthetypethatitinferredforyoursubexpression
• Bytheway,thiswasoneofthenonsensicalexpressionsthatdidnotevaluatetoavalue
• Itisagoodthingthatthisexpressiondoesnottypecheck!
# "hello" + 1;; Error: This expression has type string but an expression was expected of type int
53
TypeCheckingRules• Viola'ngtherules:
• Apossiblefix:
• OneofthekeystobecomingagoodMLprogrammeristounderstandtypeerrormessages.
# "hello" + 1;; Error: This expression has type string but an expression was expected of type int
# "hello" ^ (string_of_int 1);; - : string = "hello1"
54
OVERALLSUMMARY:ASHORTINTRODUCTIONTOFUNCTIONALPROGRAMMING
55
OCamlOCamlisafunc9onalprogramminglanguage
– Javagetsmostworkdonebymodifyingdata
– OCamlgetsmostworkdonebyproducingnew,immutabledata
OCamlisatypedprogramminglanguage
– thetypeofanexpressioncorrectlypredictsthekindofvaluetheexpressionwillgeneratewhenitisexecuted
– typeshelpusunderstandandwriteourprograms– thetypesystemissound;thelanguageissafe
56