Tokyo F# meetup 14-08-03

  • Published on
    23-Aug-2014

  • View
    869

  • Download
    20

DESCRIPTION

Functional programming with F# (FSharp)

Transcript

Functional thinking, a universal tool for the digital world Nicolas Rolland August 3, 2014 Nicolas Rolland Functional prototyping August 3, 2014 1 / 34 Table of Contents 1 Types why types ? Warm-up exercices IEnumerable and IObservable 2 Universals, programming against the interface and existentials universals it sounds like L in SOLID .. existentials 3 Prototyping the functional way Parser combinator Nicolas Rolland Functional prototyping August 3, 2014 2 / 34 Table of Contents 1 Types why types ? Warm-up exercices IEnumerable and IObservable 2 Universals, programming against the interface and existentials universals it sounds like L in SOLID .. existentials 3 Prototyping the functional way Parser combinator Nicolas Rolland Functional prototyping August 3, 2014 3 / 34 Types What is a type ? Nicolas Rolland Functional prototyping August 3, 2014 4 / 34 Types What is a type ? Type A type is a set of values. Nicolas Rolland Functional prototyping August 3, 2014 4 / 34 Types What is a type ? Type A type is a set of values. why do we need to think of it in typed functional programming ? a value is a value e.g. 1 Nicolas Rolland Functional prototyping August 3, 2014 4 / 34 Types What is a type ? Type A type is a set of values. why do we need to think of it in typed functional programming ? a value is a value e.g. 1 a function is a value too ! let plus = (+) //fun x y -> x + y let plusone = plus 1 //fun x -> x + 1 let three = plusone 2 //3 Nicolas Rolland Functional prototyping August 3, 2014 4 / 34 Types What is a type ? Type A type is a set of values. why do we need to think of it in typed functional programming ? a value is a value e.g. 1 a function is a value too ! let plus = (+) //fun x y -> x + y let plusone = plus 1 //fun x -> x + 1 let three = plusone 2 //3 hence everything is a value, everything has a type ! Nicolas Rolland Functional prototyping August 3, 2014 4 / 34 Using types Nicolas Rolland Functional prototyping August 3, 2014 5 / 34 Using types by restriction we get correctness - The computer tells us the errors Nicolas Rolland Functional prototyping August 3, 2014 5 / 34 Using types by restriction we get correctness - The computer tells us the errors restriction tells readers a specication - We can communicate to other people Nicolas Rolland Functional prototyping August 3, 2014 5 / 34 Using types by restriction we get correctness - The computer tells us the errors restriction tells readers a specication - We can communicate to other people Types should be helping you, not get in your way. No need to write the types in F#. Less work AND more security ! You can write the types for the purpose of communication with others Nicolas Rolland Functional prototyping August 3, 2014 5 / 34 Warm-up exercices Nicolas Rolland Functional prototyping August 3, 2014 6 / 34 what can I do with a value of this type ? Type1 () T Nicolas Rolland Functional prototyping August 3, 2014 7 / 34 what can I do with a value of this type ? Type1 () T let a = (fun () -> 3) : unit -> int Nicolas Rolland Functional prototyping August 3, 2014 7 / 34 what can I do with a value of this type ? Type1 () T let a = (fun () -> 3) : unit -> int lazy values ! Nicolas Rolland Functional prototyping August 3, 2014 7 / 34 what can I do with a value of this type ? Type1 () T let a = (fun () -> 3) : unit -> int lazy values ! let delayedValue = fun () -> someComputationForLater()) T = () T Nicolas Rolland Functional prototyping August 3, 2014 7 / 34 what can I do with a value of this type ? Type1 () T let a = (fun () -> 3) : unit -> int lazy values ! let delayedValue = fun () -> someComputationForLater()) T = () T let delay x = fun () x : T (() T) let force f = f () : (() T) T delay force = Id()T force delay = IdT Nicolas Rolland Functional prototyping August 3, 2014 7 / 34 what can I do with a value of this type ? Type2 type Type2 < T >= | Case1 of (T Type2 < T >) | Case0 Nicolas Rolland Functional prototyping August 3, 2014 8 / 34 what can I do with a value of this type ? Type2 type Type2 < T >= | Case1 of (T Type2 < T >) | Case0 let a = Case1(1,Case1(2,Case1(3,Case0))) Nicolas Rolland Functional prototyping August 3, 2014 8 / 34 what can I do with a value of this type ? Type2 type Type2 < T >= | Case1 of (T Type2 < T >) | Case0 let a = Case1(1,Case1(2,Case1(3,Case0))) This is a list ! match l with | Case1(value, rest) -> ... //do something with value | Case0 -> ... //do something else Nicolas Rolland Functional prototyping August 3, 2014 8 / 34 what can I do with a value of this type ? Type3 type RComp < T >= | NotYet of (() RComp < T >) | Finished of T Nicolas Rolland Functional prototyping August 3, 2014 9 / 34 what can I do with a value of this type ? Type3 type RComp < T >= | NotYet of (() RComp < T >) | Finished of T let c = NotYet(fun () -> (*first part*) NotYet (fun () -> (*second part*) Finished pi)) Nicolas Rolland Functional prototyping August 3, 2014 9 / 34 what can I do with a value of this type ? Type3 type RComp < T >= | NotYet of (() RComp < T >) | Finished of T let c = NotYet(fun () -> (*first part*) NotYet (fun () -> (*second part*) Finished pi)) Resumable computation ! Nicolas Rolland Functional prototyping August 3, 2014 9 / 34 can you recognize IEnumerable ? What is a value of type IEnumerable ? Nicolas Rolland Functional prototyping August 3, 2014 10 / 34 can you recognize IEnumerable ? What is a value of type IEnumerable ? a sequence of items Nicolas Rolland Functional prototyping August 3, 2014 10 / 34 can you recognize IEnumerable ? What is a value of type IEnumerable ? a sequence of items Item type Item of T = | Finished | Value of T Nicolas Rolland Functional prototyping August 3, 2014 10 / 34 can you recognize IEnumerable ? What is a value of type IEnumerable ? a sequence of items Item type Item of T = | Finished | Value of T IEnumerable type IEnumerable < T > = () (() Item of T) Nicolas Rolland Functional prototyping August 3, 2014 10 / 34 Object Oriented way Nicolas Rolland Functional prototyping August 3, 2014 11 / 34 Object Oriented way public interface IEnumerator { bool MoveNext(); Object Current { get; } void Reset(); } public interface IEnumerable { IEnumerator GetEnumerator(); } How can I read the protocol ? Should I call MoveNext rst ? What is the value of current after enumeration is nished ? How can I make sure current is not used after enumeration is nished ? Nicolas Rolland Functional prototyping August 3, 2014 11 / 34 IObservable / Reactive type IObservable < T > = (Item of T ()) () Nicolas Rolland Functional prototyping August 3, 2014 12 / 34 IObservable / Reactive type IObservable < T > = (Item of T ()) () IEnumerable type IEnumerable < T > = () (() Item of T) Dont they look similar .... ? Nicolas Rolland Functional prototyping August 3, 2014 12 / 34 IObservable / Reactive type IObservable < T > = (Item of T ()) () IEnumerable type IEnumerable < T > = () (() Item of T) Dont they look similar .... ? why ? Nicolas Rolland Functional prototyping August 3, 2014 12 / 34 What is a type - take 2 What is a type and why do we need to think of it ? Nicolas Rolland Functional prototyping August 3, 2014 13 / 34 What is a type - take 2 What is a type and why do we need to think of it ? Type A type is a computable specication Nicolas Rolland Functional prototyping August 3, 2014 13 / 34 What is a type - take 2 What is a type and why do we need to think of it ? Type A type is a computable specication Domain Driven Design : the architecture is the code Nicolas Rolland Functional prototyping August 3, 2014 13 / 34 Together Nicolas Rolland Functional prototyping August 3, 2014 14 / 34 Table of Contents 1 Types why types ? Warm-up exercices IEnumerable and IObservable 2 Universals, programming against the interface and existentials universals it sounds like L in SOLID .. existentials 3 Prototyping the functional way Parser combinator Nicolas Rolland Functional prototyping August 3, 2014 15 / 34 Universals Type let empty () = System.Collections.Generic.List() let stringList = empty() do stringList.Add("hello") let intList = empty() do intList.Add(1) type List = | Empty | Cons of (T * List) let stringList = Empty let stringList = Cons ("hello", stringList) let intList = Empty let intList = Cons (1, intList) What is the type of Empty Nicolas Rolland Functional prototyping August 3, 2014 16 / 34 Universals Type let empty () = System.Collections.Generic.List() let stringList = empty() do stringList.Add("hello") let intList = empty() do intList.Add(1) type List = | Empty | Cons of (T * List) let stringList = Empty let stringList = Cons ("hello", stringList) let intList = Empty let intList = Cons (1, intList) What is the type of Empty ? Empty : T. List < T > What is the type of Cons Nicolas Rolland Functional prototyping August 3, 2014 16 / 34 Universals Type let empty () = System.Collections.Generic.List() let stringList = empty() do stringList.Add("hello") let intList = empty() do intList.Add(1) type List = | Empty | Cons of (T * List) let stringList = Empty let stringList = Cons ("hello", stringList) let intList = Empty let intList = Cons (1, intList) What is the type of Empty ? Empty : T. List < T > What is the type of Cons ? Cons : T. T List < T > List < T > Nicolas Rolland Functional prototyping August 3, 2014 16 / 34 Universals What is the type of Empty ? Empty : T. List < T > I dont need to know anything about the type to do my job, I will only refer to it opaquely as T implementer of List < T > does not know T user of List < T > provide the type T Nicolas Rolland Functional prototyping August 3, 2014 17 / 34 Liskov substitution principle - Program to interface type ICurrencyQuoteProvider = abstract getQuote : string -> double type BloombergCurrencyQuoteProvider(licenceToken:obj) = interface ICurrencyQuoteProvider with member this.getQuote cur = 120.0 //implementation logic type TestQuoteProvider() = interface ICurrencyQuoteProvider with member this.getQuote cur = 120.0 //program to **interface** type Basket(curProv:ICurrencyQuoteProvider) = //add to basket etc... member this.getTotalJPY () = 0.0 //implementation logic member this.getTotalIn cur = this.getTotalJPY () * curProv.getQuote cur let testBasket = Basket(TestQuoteProvider()) let prodBasket = Basket(BloombergCurrencyQuoteProvider(...)) Nicolas Rolland Functional prototyping August 3, 2014 18 / 34 Existentials Interfaces allows to abstract in object oriented programming Like universals types, it hides something, but what is the relation ? Nicolas Rolland Functional prototyping August 3, 2014 19 / 34 Existentials Interfaces allows to abstract in object oriented programming Like universals types, it hides something, but what is the relation ? Functional is Mathematics ! Abstraction in FP has to have a precise denition related to universals ! Nicolas Rolland Functional prototyping August 3, 2014 19 / 34 Existentials Interfaces allows to abstract in object oriented programming Like universals types, it hides something, but what is the relation ? Functional is Mathematics ! Abstraction in FP has to have a precise denition related to universals ! Universals denition empty : T. () List < T > suggests existentials absStack : T{empty : () T push : int T T pop : T T top : T int} Ill use whatever type I want here; you wont know anything about the type, so you can only refer to it opaquely as X Nicolas Rolland Functional prototyping August 3, 2014 19 / 34 absStack : T{empty : () T push : int T T pop : T T top : T int} implementer Know about the specic type T user does not know about the specic type T, only about the interface Nicolas Rolland Functional prototyping August 3, 2014 20 / 34 duality Nicolas Rolland Functional prototyping August 3, 2014 21 / 34 duality IEnumerable vs IObservable Universals vs Existentials are examples of applying duality Nicolas Rolland Functional prototyping August 3, 2014 21 / 34 Erik Meijer - he will reverse all your arrows Nicolas Rolland Functional prototyping August 3, 2014 22 / 34 Functional programming and duality is old : we know it works Nicolas Rolland Functional prototyping August 3, 2014 23 / 34 encoding in Fsharp // t . Stack(t) type StackOps = { empty :Rep isEmpty :Rep -> bool push : (int *Rep) -> Rep pop :Rep -> Rep top :Rep -> int } // t. Stack(t) [] type ExistentialStack()= // x. ( t . Stack(t) > x) > x = t. Stack(t) abstract Apply : StackClient -> x and Stack(e:Rep,ops:StackOps)= inherit ExistentialStack() member this.witness = e member this.getOps = ops override this.Apply(mc) = mc.Apply(this) and StackClient = interface // t. Stack(t) > y abstract member Apply : Stack -> y Nicolas Rolland Functional prototyping August 3, 2014 24 / 34 stack demo Nicolas Rolland Functional prototyping August 3, 2014 25 / 34 Existentials - References Luca Cardelli, Peter Wegner (1985) On Understanding Types, Data Abstraction, and Polymorphism William Cook (2009) On Understanding Data Abstraction, Revisited Nicolas Rolland Functional prototyping August 3, 2014 26 / 34 Table of Contents 1 Types why types ? Warm-up exercices IEnumerable and IObservable 2 Universals, programming against the interface and existentials universals it sounds like L in SOLID .. existentials 3 Prototyping the functional way Parser combinator Nicolas Rolland Functional prototyping August 3, 2014 27 / 34 How do we go from here to there ? string [a number is like 1234 but can also be 9.12 ] value let b = List([String "a" String "number" String "is" String "like" NumberI 1234 List ([ String "but" String "can" String "also" String "be" NumberF 9.12 ]) ]) Nicolas Rolland Functional prototyping August 3, 2014 28 / 34 How do we go from here to there ? string [a number is like 1234 but can also be 9.12 ] value let b = List([String "a" String "number" String "is" String "like" NumberI 1234 List ([ String "but" String "can" String "also" String "be" NumberF 9.12 ]) ]) This is a job for ..... Nicolas Rolland Functional prototyping August 3, 2014 28 / 34 How do we go from here to there ? string [a number is like 1234 but can also be 9.12 ] value let b = List([String "a" String "number" String "is" String "like" NumberI 1234 List ([ String "but" String "can" String "also" String "be" NumberF 9.12 ]) ]) This is a job for ..... grep ? Nicolas Rolland Functional prototyping August 3, 2014 28 / 34 How do we go from here to there ? string [a number is like 1234 but can also be 9.12 ] value let b = List([String "a" String "number" String "is" String "like" NumberI 1234 List ([ String "but" String "can" String "also" String "be" NumberF 9.12 ]) ]) This is a job for ..... grep ? imperative ? Nicolas Rolland Functional prototyping August 3, 2014 28 / 34 How do we go from here to there ? string [a number is like 1234 but can also be 9.12 ] value let b = List([String "a" String "number" String "is" String "like" NumberI 1234 List ([ String "but" String "can" String "also" String "be" NumberF 9.12 ]) ]) This is a job for ..... grep ? imperative ? or... Nicolas Rolland Functional prototyping August 3, 2014 28 / 34 How do we go from here to there ? string [a number is like 1234 but can also be 9.12 ] value let b = List([String "a" String "number" String "is" String "like" NumberI 1234 List ([ String "but" String "can" String "also" String "be" NumberF 9.12 ]) ]) This is a job for ..... grep ? imperative ? or... ! Nicolas Rolland Functional prototyping August 3, 2014 28 / 34 lambda man ! Nicolas Rolland Functional prototyping August 3, 2014 29 / 34 start with the types Nicolas Rolland Functional prototyping August 3, 2014 30 / 34 start with the types value type type Val = | List of Val list | NumberI of int | NumberF of double | String of string value let b = List([String "a" String "number" String "is" String "like" NumberI 1234 List ([ String "but" String "can" String "also" String "be" NumberF 9.12 ]) ]) Nicolas Rolland Functional prototyping August 3, 2014 30 / 34 parser return type - rst try type ParseReturn = | Success of ret | Failure of string type Parser = List -> ParseReturn * List Nicolas Rolland Functional prototyping August 3, 2014 31 / 34 parser return type - rst try type ParseReturn = | Success of ret | Failure of string type Parser = List -> ParseReturn * List reading the parser type a parser takes a list of token in it returns a ParserReturn , and the tokens not yet processed Nicolas Rolland Functional prototyping August 3, 2014 31 / 34 parser return type - rst try type ParseReturn = | Success of ret | Failure of string type Parser = List -> ParseReturn * List reading the parser type a parser takes a list of token in it returns a ParserReturn , and the tokens not yet processed a ParserReturn is the value represented by the token consumed Ok, but........ 9.12 : 9 is a number.. but if we recognize 9 as 9 only, what do we do for .12 ? = the result of a parser depends also on the rest of the string If it matters, it should be part of the returned type of a parser ! Nicolas Rolland Functional prototyping August 3, 2014 31 / 34 parser return type type ParseReturn = | Success of ret *(token list) | Failure of string type Parser = token list -> ParseReturn e.g. 9.12 reading the parser type Each success contains a recognized value along with the rest Because the notion of what is the rest is dependent on the Val produced ParseReturn now contains a coherent and actionable unit of information Nicolas Rolland Functional prototyping August 3, 2014 32 / 34 demo time Nicolas Rolland Functional prototyping August 3, 2014 33 / 34 There are many more tricks to practice Nicolas Rolland Functional prototyping August 3, 2014 34 / 34 The End Nicolas Rolland Functional prototyping August 3, 2014 35 / 34