Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Programming with pure functions

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Programming with pure functions

Functional programming is taking the world by storm and with it comes the notion of programming with pure functions. We'll explore how this insight can help us build better software by improving how we reason about our programs. By learning about the mathematics of functions we'll build an intuition for thinking functionally, but we'll stay away from difficult mathematical notation or jargon. All code examples used in the talk will be in TypeScript, although we will stick to easy examples. No prerequisite knowledge of mathematics is required. The talk will introduce the concepts of Sets and Functions.

Avatar for Janne Siera

Janne Siera

October 22, 2019

More Decks by Janne Siera

Other Decks in Programming

Transcript

  1. Chapter 1: Excel Analytics Chapter 2: Procedures and Maps Chapter

    3: Working with Maps Chapter 4: ANDs and ORs Chapter 5: From whiteboards to pipelines
  2. OUR MISSION OUR MISSION Create a tool to examine excel

    data to provide business analytics to an international company.
  3. THE DATA THE DATA // Mock const readExcel = ():

    Array<Invoice> => { return [ { InvoiceId: "101", CountryCode: "BE" }, { InvoiceId: "102", CountryCode: "BR" }, { InvoiceId: "103", CountryCode: "BR" } ] }
  4. THE DATA THE DATA // So we get them like

    this const invoices: Array<Invoice> = readExcel(); // Mock const readExcel = (): Array<Invoice> => { return [ { InvoiceId: "101", CountryCode: "BE" }, { InvoiceId: "102", CountryCode: "BR" }, { InvoiceId: "103", CountryCode: "BR" } ] }
  5. HOW MANY BELGIAN INVOICES? HOW MANY BELGIAN INVOICES? const getBelgianInvoices

    = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BE') { invoices.splice(i,1); } } return invoices; }
  6. HOW MANY BELGIAN INVOICES? HOW MANY BELGIAN INVOICES? const getNumberOfBelgianInvoices

    = (): number => { const invoices = readExcel(); const belgianInvoices = getBelgianInvoices(invoices); return belgianInvoices.length; } const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BE') { invoices.splice(i,1); } } return invoices; }
  7. HOW MANY BELGIAN INVOICES? HOW MANY BELGIAN INVOICES? getNumberOfBelgianInvoices(); //

    1 const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BE') { invoices.splice(i,1); } } return invoices; } const getNumberOfBelgianInvoices = (): number => { const invoices = readExcel(); const belgianInvoices = getBelgianInvoices(invoices); return belgianInvoices.length; }
  8. HOW MANY BRAZILIAN INVOICES? HOW MANY BRAZILIAN INVOICES? const getBrazilianInvoices

    = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BR') { invoices.splice(i,1); } } return invoices; } const getNumberOfBrazilianInvoices = (): number => { const invoices = readExcel(); const brazilianInvoices = getBrazilianInvoices(invoices); return brazilianInvoices.length; }
  9. HOW MANY BRAZILIAN INVOICES? HOW MANY BRAZILIAN INVOICES? 'BR' const

    getBrazilianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== ) { invoices.splice(i,1); } } return invoices; } const getNumberOfBrazilianInvoices = (): number => { const invoices = readExcel(); const brazilianInvoices = getBrazilianInvoices(invoices); return brazilianInvoices.length; }
  10. HOW MANY BRAZILIAN INVOICES? HOW MANY BRAZILIAN INVOICES? getNumberOfBrazilianInvoices(); //

    2 const getBrazilianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BR') { invoices.splice(i,1); } } return invoices; } const getNumberOfBrazilianInvoices = (): number => { const invoices = readExcel(); const brazilianInvoices = getBrazilianInvoices(invoices); return brazilianInvoices.length; }
  11. FAVORITE PAYMENT METHOD? FAVORITE PAYMENT METHOD? const calculateFavoritePaymentMethod = ():

    PaymentMethod => { const numberOfBelgianInvoices = getNumberOfBelgianInvoices(); const numberOfBrazilianInvoices = getNumberOfBrazilianInvoices(); if(numberOfBelgianInvoices > numberOfBrazilianInvoices) return PaymentMethod.Bancontact; else if (numberOfBrazilianInvoices > numberOfBelgianInvoices) return PaymentMethod.Visa else throw "Can't decide" } enum PaymentMethod { Bancontact, Visa, Mastercard }
  12. FAVORITE PAYMENT METHOD? FAVORITE PAYMENT METHOD? Expected output: 1 enum

    PaymentMethod { Bancontact, /* 0 */ Visa, /* 1 */ Mastercard /* 2 */ } const readExcel = () => { return [ { InvoiceId: "101", CountryCode: "BE" }, // Bancontact 0 { InvoiceId: "102", CountryCode: "BR" }, // Visa 1 { InvoiceId: "103", CountryCode: "BR" } // Visa 1 ] }
  13. FAVORITE PAYMENT METHOD? FAVORITE PAYMENT METHOD? calculateFavoritePaymentMethod(); // 1 const

    calculateFavoritePaymentMethod = (): PaymentMethod => { const numberOfBelgianInvoices = getNumberOfBelgianInvoices(); const numberOfBrazilianInvoices = getNumberOfBrazilianInvoices(); if(numberOfBelgianInvoices > numberOfBrazilianInvoices) return PaymentMethod.Bancontact; else if (numberOfBrazilianInvoices > numberOfBelgianInvoices) return PaymentMethod.Visa else throw "Can't decide" }
  14. FAVORITE PAYMENT METHOD? FAVORITE PAYMENT METHOD? getNumberOfBelgianInvoices() getNumberOfBrazilianInvoices() const calculateFavoritePaymentMethod

    = (): PaymentMethod => { const numberOfBelgianInvoices = ; const numberOfBrazilianInvoices = ; if(numberOfBelgianInvoices > numberOfBrazilianInvoices) return PaymentMethod.Bancontact; else if (numberOfBrazilianInvoices > numberOfBelgianInvoices) return PaymentMethod.Visa else throw "Can't decide" } calculateFavoritePaymentMethod(); // 1
  15. FAVORITE PAYMENT METHOD? FAVORITE PAYMENT METHOD? const invoices = readExcel();

    getBelgianInvoices(invoices).length getBrazilianInvoices(invoices).length const calculateFavoritePaymentMethod = (): PaymentMethod => { const numberOfBelgianInvoices = ; const numberOfBrazilianInvoices = ; if(numberOfBelgianInvoices > numberOfBrazilianInvoices) return PaymentMethod.Bancontact; else if (numberOfBrazilianInvoices > numberOfBelgianInvoices) return PaymentMethod.Visa else throw "Can't decide" }
  16. FAVORITE PAYMENT METHOD? FAVORITE PAYMENT METHOD? calculateFavoritePaymentMethod(); // 0 const

    calculateFavoritePaymentMethod = (): PaymentMethod => { const invoices = readExcel(); const numberOfBelgianInvoices = getBelgianInvoices(invoices).length; const numberOfBrazilianInvoices = getBrazilianInvoices(invoices).length; if(numberOfBelgianInvoices > numberOfBrazilianInvoices) return PaymentMethod.Bancontact; else if (numberOfBrazilianInvoices > numberOfBelgianInvoices) return PaymentMethod.Visa else throw "Can't decide" }
  17. FAVORITE PAYMENT METHOD? FAVORITE PAYMENT METHOD? invoices invoices invoices const

    calculateFavoritePaymentMethod = (): PaymentMethod => { const = readExcel(); const numberOfBelgianInvoices = getBelgianInvoices( ).length; const numberOfBrazilianInvoices = getBrazilianInvoices( ).length; if(numberOfBelgianInvoices > numberOfBrazilianInvoices) return PaymentMethod.Bancontact; else if (numberOfBrazilianInvoices > numberOfBelgianInvoices) return PaymentMethod.Visa else throw "Can't decide" } calculateFavoritePaymentMethod(); // 0
  18. UPDATING THE EXCEL UPDATING THE EXCEL LastUpdated: Date type Invoice

    = { InvoiceId: string; CountryCode: string; }
  19. UPDATING THE EXCEL UPDATING THE EXCEL LastUpdated: new Date() LastUpdated:

    new Date() LastUpdated: new Date() type Invoice = { InvoiceId: string; CountryCode: string; LastUpdated: Date } const readExcel = (): Array<Invoice> => { return [ { InvoiceId: "101", CountryCode: "BE", }, { InvoiceId: "102", CountryCode: "BR", }, { InvoiceId: "103", CountryCode: "BR", } ] }
  20. UPDATING THE EXCEL UPDATING THE EXCEL const createExcel = (fileName:

    string, invoices: Array<Invoice>) => { console.log(invoices); } type Invoice = { InvoiceId: string; CountryCode: string; LastUpdated: Date } const readExcel = (): Array<Invoice> => { return [ { InvoiceId: "101", CountryCode: "BE", LastUpdated: new Date() }, { InvoiceId: "102", CountryCode: "BR", LastUpdated: new Date() }, { InvoiceId: "103", CountryCode: "BR", LastUpdated: new Date() } ] }
  21. UPDATING THE EXCEL UPDATING THE EXCEL const updateInvoices = async

    () => { const invoices = readExcel(); for(var i=0; i < invoices.length; i++) { invoices[0].LastUpdated = new Date(); // Update other information } // Create excel with all updated invoices const updatedInvoices = invoices .filter(i => i.LastUpdated.getTime() === new Date().getTime()); createExcel("Update Report", updatedInvoices); }
  22. UPDATING THE EXCEL UPDATING THE EXCEL Output: Prints all 3

    updated invoices to the console const updateInvoices = async () => { const invoices = readExcel(); for(var i=0; i < invoices.length; i++) { invoices[0].LastUpdated = new Date(); // Update other information } // Create excel with all updated invoices const updatedInvoices = invoices .filter(i => i.LastUpdated.getTime() === new Date().getTime()); createExcel("Update Report", updatedInvoices); }
  23. UPDATING THE EXCEL UPDATING THE EXCEL await sleep(1000); const updateInvoices

    = async () => { const invoices = readExcel(); for(var i=0; i < invoices.length; i++) { invoices[0].LastUpdated = new Date(); // Update other information } // Create excel with all updated invoices const updatedInvoices = invoices .filter(i => i.LastUpdated.getTime() === new Date().getTime()); createExcel("Update Report", updatedInvoices); }
  24. UPDATING THE EXCEL UPDATING THE EXCEL Output: Prints an empty

    array to the console const updateInvoices = async () => { const invoices = readExcel(); for(var i=0; i < invoices.length; i++) { invoices[0].LastUpdated = new Date(); // Update other information } await sleep(1000); // Create excel with all updated invoices const updatedInvoices = invoices .filter(i => i.LastUpdated.getTime() === new Date().getTime()); createExcel("Update Report", updatedInvoices); }
  25. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Create references Mutate references
  26. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Iterate lists Mutate references Create references
  27. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Throw Exceptions Mutate references Create references Iterate lists
  28. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Return values Mutate references Create references Iterate lists Throw Exceptions
  29. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Make an HTTP request Mutate references Create references Iterate lists Throw Exceptions Return values
  30. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Read from a file Mutate references Create references Iterate lists Throw Exceptions Return values Make an HTTP request
  31. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Write to a file Mutate references Create references Iterate lists Throw Exceptions Return values Make an HTTP request Read from a file
  32. WHAT A PROCEDURE CAN DO WHAT A PROCEDURE CAN DO

    Connect, read and write to a database Mutate references Create references Iterate lists Throw Exceptions Return values Make an HTTP request Read from a file Write to a file
  33. A PROCEDURE CAN DO A PROCEDURE CAN DO Anything! Mutate

    references Create references Iterate lists Throw Exceptions Return values Make an HTTP request Read from a file Write to a file Connect, read and write to a database
  34. // Reads from a file const getNumberOfBelgianInvoices = (): number

    => { ... } // Mutates a reference const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { ... }
  35. // Reads from a file // Throws exception const calculateFavoritePaymentMethod

    = (): PaymentMethod => { ... } // Mutates a reference const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { ... } // Reads from a file const getNumberOfBelgianInvoices = (): number => { ... }
  36. WHAT IS A MAP? WHAT IS A MAP? We're looking

    for a simpler way of doing things.
  37. Rule #2: All input elements need to be accounted for

    Rule #1: Only one arrow per input element
  38. A map associates the elements of an input set with

    the elements of an output set. Rule #1: Only one arrow per input element Rule #2: All input elements need to be accounted for
  39. SET ≈ TYPE SET ≈ TYPE bool is { True,

    False } number is { ..., -2, -1, 0, 1, 2, ... }
  40. SET ≈ TYPE SET ≈ TYPE bool is { True,

    False } number is { ..., -2, -1, 0, 1, 2, ... } string is { "", "a", "aa", "aaa", ..., "hello", ..., "dsfewsdf", ..., "hello world!", ... }
  41. SET ≈ TYPE SET ≈ TYPE bool is { True,

    False } number is { ..., -2, -1, 0, 1, 2, ... } string is { "", "a", "aa", "aaa", ..., "hello", ..., "dsfewsdf", ..., "hello world!", ... } Countries is { Belgium, Brazil }
  42. FAVORITEPAYMENTMETHOD FAVORITEPAYMENTMETHOD const FavoritePaymentMethod = (country: Countries): PaymentMethod => {

    ... } enum Countries { Belgium, Brazil } // Input set enum PaymentMethod { Bancontact, Visa, Mastercard } // Output set
  43. FAVORITEPAYMENTMETHOD FAVORITEPAYMENTMETHOD switch(country) { case Countries.Belgium: return PaymentMethod.Bancontact; } enum

    Countries { Belgium, Brazil } // Input set enum PaymentMethod { Bancontact, Visa, Mastercard } // Output set const FavoritePaymentMethod = (country: Countries): PaymentMethod => { }
  44. FAVORITEPAYMENTMETHOD FAVORITEPAYMENTMETHOD TypeScript error: Function lacks ending return statement and

    return type does not include 'undefined' enum Countries { Belgium, Brazil } // Input set enum PaymentMethod { Bancontact, Visa, Mastercard } // Output set const FavoritePaymentMethod = (country: Countries): PaymentMethod => switch(country) { case Countries.Belgium: return PaymentMethod.Bancontact; } }
  45. FAVORITEPAYMENTMETHOD FAVORITEPAYMENTMETHOD case Countries.Brazil: return PaymentMethod.Mastercard; enum Countries { Belgium,

    Brazil } // Input set enum PaymentMethod { Bancontact, Visa, Mastercard } // Output set const FavoritePaymentMethod = (country: Countries): PaymentMethod => switch(country) { case Countries.Belgium: return PaymentMethod.Bancontact; } }
  46. FAVORITEPAYMENTMETHOD FAVORITEPAYMENTMETHOD enum Countries { Belgium, Brazil } // Input

    set enum PaymentMethod { Bancontact, Visa, Mastercard } // Output set const FavoritePaymentMethod = (country: Countries): PaymentMethod => switch(country) { case Countries.Belgium: return PaymentMethod.Bancontact; case Countries.Brazil: return PaymentMethod.Mastercard; } }
  47. INCREMENT INCREMENT const AbsoluteValue = (number: number): number => {

    if(number >= 0) return number else return (-1) * number; }
  48. FUNCTIONS AS MAPS FUNCTIONS AS MAPS Referential Transparency Functional Equivalence

    const IncrementA = (number: number): number => { return number + 1; } const IncrementB = (number: number): number => { return number + 2 - 1; }
  49. FUNCTIONS AS MAPS FUNCTIONS AS MAPS PURE FUNCTIONS PURE FUNCTIONS

    Transform input to output No 'side effects'
  50. "We turn our powerful procedures that can do many things

    into very simple 'pure functions'."
  51. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP // Old const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BE') { invoices.splice(i,1); } } return invoices; }
  52. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP // Old invoices.splice(i,1) // Implicit output const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BE') { ; } } return invoices; }
  53. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP // New: Create a new list, and copy over const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { const newList: Array<Invoice> = []; for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BE') { // Do nothing } else { newList.push(invoices[i]); } } return invoices; }
  54. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP // New: Create a new list, and copy over const newList: Array<Invoice> = [];// Explicit output newList.push(invoices[i]); const getBelgianInvoices = (invoices: Array<Invoice>): Array<Invoice> => { for (var i = invoices.length - 1; i >= 0; i--) { if(invoices[i].CountryCode !== 'BE') { // Do nothing } else { } } return invoices; }
  55. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP // Old const updateInvoice = (invoice: Invoice): void => { invoice.LastUpdated = new Date(); // Update other information } const updateInvoices = async (): void => { const invoices = readExcel(); for(var i=0; i < invoices.length; i++) { updateInvoice(invoices[i]); } // Create excel with all updated invoices const updatedInvoices = invoices .filter(i => i.LastUpdated.getTime() === new Date().getTime()); createExcel("Update Report", updatedInvoices); }
  56. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP // Old new Date() // Implicit input new Date().getTime()) // Implicit const updateInvoice = (invoice: Invoice): void => { invoice.LastUpdated = ; // Update other information } const updateInvoices = async (): void => { const invoices = readExcel(); for(var i=0; i < invoices.length; i++) { updateInvoice(invoices[i]); } // Create excel with all updated invoices const updatedInvoices = invoices .filter(i => i.LastUpdated.getTime() === ; createExcel("Update Report", updatedInvoices); }
  57. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP // New: Make it explicit , date: Date date const date = new Date(); , date date const updateInvoice = (invoice: Invoice ): void => { invoice.LastUpdated = ; // Update other information } const updateInvoices = async (): void => { const invoices = readExcel(); for(var i=0; i < invoices.length; i++) { updateInvoice(invoices[i] ); } // Create excel with all updated invoices const updatedInvoices = invoices .filter(i => i.LastUpdated.getTime() === .getTime()); createExcel("Update Report", updatedInvoices); }
  58. TURNING A PROCESS INTO A MAP TURNING A PROCESS INTO

    A MAP /* Bonus */ Invoice // Create and return a new invoice with updated values const updatedInvoices = invoices .map(i => updateInvoice(i, date)) .filter(i => i.LastUpdated.getTime() === date.getTime()); const updateInvoice = (invoice: Invoice, date: Date): => { } const updateInvoices = async (): void => { const invoices = readExcel(); const date = new Date(); createExcel("Update Report", updatedInvoices); }
  59. WHAT IS THE COUNTRY ASSOCIATED WITH WHAT IS THE COUNTRY

    ASSOCIATED WITH AN INVOICE? AN INVOICE?
  60. WHAT IS THE COUNTRY ASSOCIATED WITH AN WHAT IS THE

    COUNTRY ASSOCIATED WITH AN INVOICE? INVOICE? const toCountry = (invoice: Invoice): Countries => { if (invoice.CountryCode === 'BE') return Countries.Belgium; if (invoice.CountryCode === 'BR') return Countries.Brazil; return ???; }
  61. WHAT IS THE COUNTRY ASSOCIATED WITH AN WHAT IS THE

    COUNTRY ASSOCIATED WITH AN INVOICE? INVOICE? undefined const toCountry = (invoice: Invoice): Countries => { if (invoice.CountryCode === 'BE') return Countries.Belgium; if (invoice.CountryCode === 'BR') return Countries.Brazil; return ; }
  62. WHAT IS THE COUNTRY ASSOCIATED WITH AN WHAT IS THE

    COUNTRY ASSOCIATED WITH AN INVOICE? INVOICE? TypeScript error: Type 'undefined' is not assignable to type 'Countries' const toCountry = (invoice: Invoice): Countries => { if (invoice.CountryCode === 'BE') return Countries.Belgium; if (invoice.CountryCode === 'BR') return Countries.Brazil; return undefined; }
  63. WHAT IS THE COUNTRY ASSOCIATED WITH AN WHAT IS THE

    COUNTRY ASSOCIATED WITH AN INVOICE? INVOICE? Countries | undefined const toCountry = (invoice: Invoice): => { if (invoice.CountryCode === 'BE') return Countries.Belgium; if (invoice.CountryCode === 'BR') return Countries.Brazil; return undefined; }
  64. WHAT IS THE LIKELY FAVORITE PAYMENT WHAT IS THE LIKELY

    FAVORITE PAYMENT METHOD ASSOCIATED WITH AN INVOICE? METHOD ASSOCIATED WITH AN INVOICE?
  65. WHAT IS THE LIKELY FAVORITE PAYMENT METHOD WHAT IS THE

    LIKELY FAVORITE PAYMENT METHOD ASSOCIATED WITH AN INVOICE? ASSOCIATED WITH AN INVOICE? const toFavoritePaymentMethod = (invoice: Invoice): PaymentMethod => { const country: Countries | undefined = toCountry(invoice); return FavoritePaymentMethod(country); }
  66. WHAT IS THE LIKELY FAVORITE PAYMENT METHOD WHAT IS THE

    LIKELY FAVORITE PAYMENT METHOD ASSOCIATED WITH AN INVOICE? ASSOCIATED WITH AN INVOICE? TypeScript error: Argument of type 'Countries | undefined' is not assignable to parameter of type 'Countries'. Type 'undefined' is not assignable to type 'Countries'. const toFavoritePaymentMethod = (invoice: Invoice): PaymentMethod => { const country: Countries | undefined = toCountry(invoice); return FavoritePaymentMethod(country); }
  67. WHAT IS THE LIKELY FAVORITE PAYMENT METHOD WHAT IS THE

    LIKELY FAVORITE PAYMENT METHOD ASSOCIATED WITH AN INVOICE? ASSOCIATED WITH AN INVOICE? PaymentMethod | undefined => { const country: Countries | undefined = toCountry(invoice); if(country === undefined) return undefined; else return FavoritePaymentMethod(country); const toFavoritePaymentMethod = (invoice: Invoice): }
  68. WHAT IS THE LIKELY BALANCE TYPE WHAT IS THE LIKELY

    BALANCE TYPE (CREDIT/DEBIT) ASSOCIATED WITH AN (CREDIT/DEBIT) ASSOCIATED WITH AN INVOICE? INVOICE?
  69. WHAT IS THE LIKELY BALANCE TYPE (CREDIT/DEBIT) WHAT IS THE

    LIKELY BALANCE TYPE (CREDIT/DEBIT) ASSOCIATED WITH AN INVOICE? ASSOCIATED WITH AN INVOICE? enum BalanceType { Credit, Debit }
  70. WHAT IS THE LIKELY BALANCE TYPE (CREDIT/DEBIT) WHAT IS THE

    LIKELY BALANCE TYPE (CREDIT/DEBIT) ASSOCIATED WITH AN INVOICE? ASSOCIATED WITH AN INVOICE? const ToBalanceType = (country: PaymentMethod): BalanceType => { switch(country) { case PaymentMethod.Bancontact: return BalanceType.Debit; case PaymentMethod.Visa: return BalanceType.Credit; case PaymentMethod.Mastercard: return BalanceType.Credit; } } enum BalanceType { Credit, Debit }
  71. WHAT IS THE LIKELY BALANCE TYPE (CREDIT/DEBIT) WHAT IS THE

    LIKELY BALANCE TYPE (CREDIT/DEBIT) ASSOCIATED WITH AN INVOICE? ASSOCIATED WITH AN INVOICE? const countryToBalanceType = (country: Country): BalanceType => { return BalanceType(FavoritePaymentMethod(country)); } enum BalanceType { Credit, Debit } const ToBalanceType = (country: PaymentMethod): BalanceType => { switch(country) { case PaymentMethod.Bancontact: return BalanceType.Debit; case PaymentMethod.Visa: return BalanceType.Credit; case PaymentMethod.Mastercard: return BalanceType.Credit; } }
  72. WHAT IS THE LIKELY BALANCE TYPE (CREDIT/DEBIT) WHAT IS THE

    LIKELY BALANCE TYPE (CREDIT/DEBIT) ASSOCIATED WITH AN INVOICE? ASSOCIATED WITH AN INVOICE? const toFavoritePaymentMethod = (invoice: Invoice): PaymentMethod | undefined => { const country: Countries | undefined = toCountry(invoice); if(country === undefined) return undefined; else return countryToBalanceType(country); } enum BalanceType { Credit, Debit } const countryToBalanceType = (country: Country): BalanceType => { return BalanceType(FavoritePaymentMethod(country)); }
  73. MULTIPLE PARAMETERS MULTIPLE PARAMETERS type Payment = { Method: PaymentMethod

    Amount: number } const processPayment = (method: PaymentMethod, amount: number): void => { ... }
  74. MULTIPLE PARAMETERS MULTIPLE PARAMETERS const processPayment = (payment: Payment): void

    => { ... } const processPayment = (method: PaymentMethod, amount: number): void => { ... } type Payment = { Method: PaymentMethod Amount: number }
  75. REPRESENTING 'OR' REPRESENTING 'OR' const fiveEur: Currency = { Eur:

    5, Real: null } type Currency = { Eur: number | null Real: number | null }
  76. REPRESENTING 'OR' REPRESENTING 'OR' const fiveReal: Currency = { Eur:

    null, Real: 5 } type Currency = { Eur: number | null Real: number | null }
  77. REPRESENTING 'OR' REPRESENTING 'OR' const fiveEurAndReal: Currency = { Eur:

    5, Real: 5 } type Currency = { Eur: number | null Real: number | null }
  78. REPRESENTING 'OR' REPRESENTING 'OR' const noEurNoReal: Currency = { Eur:

    null, Real: null } type Currency = { Eur: number | null Real: number | null }
  79. DISCRIMINATED UNION DISCRIMINATED UNION type Eur = { Value: number

    } type Real = { Value: number } type Currency = Eur | Real const processCurrency = (val: Currency): number => { val.Value // Is this in Eur or in Real?? }
  80. DISCRIMINATED UNION DISCRIMINATED UNION tag: 'Eur' tag: 'Real' type Eur

    = { , Value: number } type Real = { , Value: number } type Currency = Eur | Real
  81. DISCRIMINATED UNION DISCRIMINATED UNION const processCurrency = (val: Currency): number

    => { switch(val.tag) { case 'Eur': // Do something with eur return val.Value; case 'Real': // Do something with real return val.Value; } // TypeScript infers all cases have been handled } type Eur = { tag: 'Eur', Value: number } type Real = { tag: 'Real', Value: number } type Currency = Eur | Real
  82. MAPS AS ELEMENTS MAPS AS ELEMENTS const Add = (a:

    number, b: number) => { return a + b; }
  83. MAPS AS ELEMENTS MAPS AS ELEMENTS const Add = (a:

    number) => { const func = (b: number) => { return a + b; } return func; } const Add = (a: number, b: number) => { return a + b; }
  84. MAPS AS ELEMENTS MAPS AS ELEMENTS const Add = (a:

    number) => (b: number) => { return a + b; } const Add = (a: number, b: number) => { return a + b; } const Add = (a: number) => { const func = (b: number) => { return a + b; } return func; }
  85. MAPS AS ELEMENTS MAPS AS ELEMENTS (a: number, b: number)

    (a: number) => (b: number) const Add = => { return a + b; } const Add = (a: number) => { const func = (b: number) => { return a + b; } return func; } const Add = => { return a + b; }
  86. PARTIAL APPLICATION PARTIAL APPLICATION const Add1: (b: number) => number

    = Add(1); const Add = (a: number) => (b: number) => { return a + b; }
  87. PARTIAL APPLICATION PARTIAL APPLICATION const x = Add1(1); // 2

    const Add = (a: number) => (b: number) => { return a + b; } const Add1: (b: number) => number = Add(1);
  88. PARTIAL APPLICATION PARTIAL APPLICATION const y = Add1(2); // 3

    const Add = (a: number) => (b: number) => { return a + b; } const Add1: (b: number) => number = Add(1); const x = Add1(1); // 2
  89. PARTIAL APPLICATION PARTIAL APPLICATION const z = Add1(3); // 4

    const Add = (a: number) => (b: number) => { return a + b; } const Add1: (b: number) => number = Add(1); const x = Add1(1); // 2 const y = Add1(2); // 3