ocaml datatypes part ii: an exercise in type design · changing fonts in an element 14 • change...

25
OCaml Datatypes Part II: An Exercise in Type Design COS 326 David Walker Princeton University slides copyright 2017 David Walker permission granted to reuse these slides for non-commercial educaJonal purposes 1

Upload: others

Post on 22-May-2020

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

OCamlDatatypesPartII:AnExerciseinTypeDesign

COS326DavidWalker

PrincetonUniversity

slidescopyright2017DavidWalkerpermissiongrantedtoreusetheseslidesfornon-commercialeducaJonalpurposes

1

Page 2: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

ExampleTypeDesign 2

IBMdevelopedGML(GeneralizeMarkupLanguage)in1969•  hSp://en.wikipedia.org/wiki/IBM_Generalized_Markup_Language•  PrecursortoSGML,HTMLandXML

:h1.Chapter 1: Introduction :p.GML supported hierarchical containers, such as :ol :li.Ordered lists (like this one), :li.Unordered lists, and :li.Definition lists :eol. as well as simple structures. :p.Markup Minimization (later generalized and formalized in SGML), allowed the end-tags to be omitted for the “h1” and “p” elements.

Page 3: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

SimplifiedGML 3

ToprocessaGMLdocument,anOCamlprogramwould:•  Readaseriesofcharactersfromatextfile&ParseGMLstructure•  RepresenttheinformaJoncontentasanOCamldatastructure•  Analyzeortransformthedatastructure•  Print/Store/CommunicateresultsWewillfocusonhowtorepresentandtransformtheinformaJoncontentofaGMLdocument.

Page 4: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

ExampleTypeDesign 4

•  AGMLdocumentconsistsof:–  alistofelements

•  Anelementiseither:–  awordormarkupappliedtoanelement

•  Markupiseither:–  italicize,bold,orafontname

Page 5: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

ExampleTypeDesign 5

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

•  AGMLdocumentconsistsof:–  alistofelements

•  Anelementiseither:–  awordormarkupappliedtoanelement

•  Markupiseither:–  italicize,bold,orafontname

Page 6: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

ExampleData 6

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

let d = [ Formatted (Bold, Formatted (Font “Arial”,

Words [“Chapter”;“One”])); Words [“It”; ”was”; ”a”; ”dark”;

”&”; ”stormy; ”night.”; "A"];

Formatted (Ital, Words[“shot”]);

Words [“rang”; ”out.”] ];;

Page 7: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Challenge 7

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.•  Ofcourse,whenweprogramfuncJonally,weimplement

changeviaafuncJonthat–  receivesonedatastructureasinput–  buildsanew(different)datastructureasanoutput

Page 8: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Challenge 8

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 9: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Challenge 9

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Technique:approachtheproblemtopdown,workondocfirst:

let rec chfonts (elts:doc) : doc =

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 10: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Challenge 10

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Technique:approachtheproblemtopdown,workondocfirst:

let rec chfonts (elts:doc) : doc = match elts with | [] -> | hd::tl ->

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 11: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Challenge 11

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Technique:approachtheproblemtopdown,workondocfirst:

let rec chfonts (elts:doc) : doc = match elts with | [] -> [] | hd::tl -> (chfont hd)::(chfonts tl)

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 12: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Changingfontsinanelement 12

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Nextworkonchangingthefontofanelement:

let rec chfont (e:elt) : elt =

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 13: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Changingfontsinanelement 13

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Nextworkonchangingthefontofanelement:

let rec chfont (e:elt) : elt = match e with | Words ws -> | Formatted(m,e) ->

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 14: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Changingfontsinanelement 14

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Nextworkonchangingthefontofanelement:

let rec chfont (e:elt) : elt = match e with | Words ws -> Words ws | Formatted(m,e) ->

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 15: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Changingfontsinanelement 15

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Nextworkonchangingthefontofanelement:

let rec chfont (e:elt) : elt = match e with | Words ws -> Words ws | Formatted(m,e) -> Formatted(chmarkup m, chfont e)

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 16: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Changingfontsinanelement 16

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Nextworkonchangingamarkup:

let chmarkup (m:markup) : markup =

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 17: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Changingfontsinanelement 17

•  Changeallofthe“Arial”fontsinadocumentto“Courier”.

•  Nextworkonchangingamarkup:

let chmarkup (m:markup) : markup = match m with | Font “Arial” -> Font “Courier” | _ -> m

type markup = Ital | Bold | Font of string type elt = Words of string list | Formatted of markup * elt type doc = elt list

Page 18: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

Summary:Changingfontsinanelement 18

•  Changeallofthe“Arial”fontsinadocumentto“Courier”•  Lesson:funcJonstructurefollowstypestructure

let chmarkup (m:markup) : markup = match m with | Font “Arial” -> Font “Courier” | _ -> m let rec chfont (e:elt) : elt = match e with | Words ws -> Words ws | Formatted(m,e) -> Formatted(chmarkup m, chfont e) let rec chfonts (elts:doc) : doc = match elts with | [] -> [] | hd::tl -> (chfont hd)::(chfonts tl)

Page 19: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

PoorStyle 19

•  ConsideragainourdefiniJonofmarkupandmarkupchange:

type markup = Ital | Bold | Font of string let chmarkup (m:markup) : markup = match m with | Font “Arial” -> Font “Courier” | _ -> m

Page 20: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

PoorStyle 20

•  Whatifwemakeachange:

type markup = Ital | Bold | Font of string | TTFont of string let chmarkup (m:markup) : markup = match m with | Font “Arial” -> Font “Courier” | _ -> m

theunderscoresilentlycatchesallpossiblealternaJvesthismaynotbewhatwewant--perhapsthereisanArialTTfontitisbeSerifwearealertedofallfuncJonswhoseimplementaJonmayneedtochange

Page 21: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

BeSerStyle 21

•  Originalcode:

type markup = Ital | Bold | Font of string let chmarkup (m:markup) : markup = match m with | Font “Arial” -> Font “Courier” | Ital | Bold -> m

Page 22: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

BeSerStyle 22

•  Updatedcode:

type markup = Ital | Bold | Font of string | TTFont of string let chmarkup (m:markup) : markup = match m with | Font “Arial” -> Font “Courier” | Ital | Bold -> m

..match m with | Font "Arial" -> Font "Courier" | Ital | Bold -> m.. Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: TTFont _

Page 23: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

BeSerStyle 23

•  Updatedcode,fixed:

•  Lesson:usethetypecheckerwherepossibletohelpyoumaintainyourcode

type markup = Ital | Bold | Font of string | TTFont of string let chmarkup (m:markup) : markup = match m with | Font "Arial" -> Font "Courier" | TTFont "Arial" -> TTFont "Courier" | Font s -> Font s | TTFont s -> TTFont s | Ital | Bold -> m

Page 24: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

AcoupleofpracJceproblems 24

•  WriteafuncJonthatgetsridofimmediatelyredundantmarkupinadocument.–  FormaSed(Ital,FormaSed(Ital,e))canbesimplifiedtoFormaSed(Ital,e)

–  writemapsandfoldsovermarkups•  Designadatatypetodescribebibliographyentriesfor

publicaJons.SomepublicaJonsarejournalarJcles,othersarebooks,andothersareconferencepapers.Journalshaveaname,numberandissue;bookshaveanISBNnumber;AlloftheseentriesshouldhaveaJtleandauthor.–  designasorJngfuncJon–  designmapsandfoldsoveryourbibliographyentries

Page 25: OCaml Datatypes Part II: An Exercise in Type Design · Changing fonts in an element 14 • Change all of the “Arial” fonts in a document to “Courier”. • Next work on changing

ToSummarize 25

•  DesignrecipeforwriJngOCamlcode:–  writedownEnglishspecificaJons

•  trytobreakproblemintoobvioussub-problems–  writedownsomesampletestcases–  writedownthesignature(types)forthecode–  usethesignaturetoguideconstrucJonofthecode:

•  tearapartinputsusingpaSernmatching– makesuretocoverallofthecases!(OCamlwilltellyou)

•  handleeachcase,buildingresultsusingdataconstructor–  thisiswherehumanintelligencecomesintoplay–  the“skeleton”givenbytypescanalmostbedoneautomaJcally!

•  cleanupyourcode–  useyoursampletests(andideallyothers)toensurecorrectness