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

Functional Programming For All

Functional Programming For All

Functional Programming For All talk given at Scala Matsuri 2016

Zach McCoy

January 30, 2016
Tweet

Other Decks in Programming

Transcript

  1. What is Functional Programming? • Programming… with functions • Functions

    as the main abstraction • Functions as first class values ʮؔ਺Λ༻͍ͨϓϩάϥϛϯάʯ ʮؔ਺Λओͳந৅Խͷಓ۩ͱ͢ΔʯʮୈҰڃ஋ͱͯ͠ͷؔ਺ʯ
  2. What is Functional Programming? • Controlled side effects • Restricts

    how we write programs, but not what we can express ʮ੍ޚ͞Εͨ෭࡞༻ʯ ʮදݱͷ෯͸ڱΊͣʹɺϓϩάϥϜͷॻ͖ํΛ੍໿͢Δʯ
  3. Functional Programming • Pure functional core with a layer of

    side effects on the outside • Side effect - an action in addition to return values • FP - Evaluating expressions • Imperative - programs are composed of statements த֩͸७ਮؔ਺Ͱͦͷ֎ଆͷ૚Ͱ෭࡞༻͕࣮ߦ͞ΕΔ '1͸ࣜΛධՁ͢Δͷʹର͠ɺ໋ྩܕ͸໋ྩจ͔Β੒Δ
  4. What is a function? • An expression involving one or

    more variables • Domain and Co-Domain • Unique mapping from D -> CD • Immutability, produces something new ؔ਺ͱ͸ͭ΋͘͠͸ෳ਺ͷ஋ʹؔ͢Δࣜ υϝΠϯͱίυϝΠϯͷҰҙରԠɺΠϛϡʔλϒϧ
  5. Pure Functions • No observable side-effects • Anything that isn’t

    returning a result • Mutation • I/O • Depends only on arguments or subset of ७ਮؔ਺͸෭࡞༻Λ࣋ͨͣɺ݁Ռ͸Ҿ਺ʹͷΈґଘ͢Δ
  6. Why does purity matter? • Side effects cause order of

    evaluation to matter • Only have to use local reasoning • Composition and reusability ෭࡞༻͸࣮ߦʗධՁॱͷߟྀ͕ඞཁʹͳΔɺہॴԽɺ ߹੒ͱ࠶ར༻ੑ
  7. Why does purity matter? • Separate the computation over the

    input from how to obtain it • Guarantees Referential Transparency ԋࢉͱೖྗΛ༩͑Δํ๏Λ෼཭ɺࢀরಁաੑΛอূ
  8. Referential Transparency • An expression can be replaced by its

    value, provided the expression is pure • A function can only be RT if the inputs are also RT • Referential Transparency enables equational reasoning ࢀরಁաੑ 35 ७ਮͳ͕ࣜͦͷ஋ͱஔ͖׵͑Մೳͳ͜ͱ ؔ਺͕ࢀরಁաͰ͋ΔͨΊʹ͸ɺೖྗ΋ಁաͰ͋Δඞཁ͕͋Δ
  9. Substitution Model def greaterThan5(i: Int): Option[Int] = if(i > 5)

    Some(i) else None def createMessage(): String = greaterThan5(3).map(x => "Was greater than 5") getOrElse "Was less than or equal to 5" def createMessage2(): String = (if(3 > 5) Some(3) else None).map(x => "Was greater than 5") getOrElse "Was less than or equal to 5" def createMessage3(): String = None.map(x => "Was greater than 5") getOrElse "Was less than or equal to 5" ஔ͖׵͑Ϟσϧ
  10. Formalize Referential Transparency • An expression, E, is said to

    be referentially transparent if E can be replaced with its value without changing the behavior of a program • Same effect and output in the end ࢀরಁաੑͷܗࣜԽɿࣜΛͦͷ஋ͱஔ͖׵͑Δ͜ͱ͕Ͱ͖Δ ϓϩάϥϜͷৼΔ෣͍͸࡞༻ΛؚΊมΘͬͯ͸͍͚ͳ͍
  11. Referential Transparency • Mathematics! • (2 * 2 = 4)

    • Returning errors as values, rather than side effecting ࢀরಁաੑ͸਺ֶ Τϥʔ͸ɺ෭࡞༻Ͱ͸ͳ͘ɺ஋Ͱฦ͢
  12. How does this tie together? • Pure functions enable Referential

    Transparency • RT enables the Substitution model and Equational Reasoning • Pure functions are a huge gain! ७ਮؔ਺㱺ࢀরಁաੑ㱺ஔ͖׵͑Ϟσϧˍ౳ࣜਪ࿦ ७ਮؔ਺㱺΢Ϛʔ
  13. Scala and FP • Scala doesn't enforce Referential Transparency •

    We have to work for it • Limit your set of tools: no vars, pulling from out of scope, exceptions 4DBMB͸ࢀরಁաੑΛڧ੍͠ͳ͍ͨΊɺࣗલͰͷରԠ͕ඞཁ
  14. Scala and FP • Given an impure function of type

    A => C we can split it into two functions • Pure function of A => B, where B is the description of the result • Impure function of type B => C which is the interpreter of the description ७ਮͰͳ͍ؔ਺"㱺$͸ɺ७ਮؔ਺"㱺#ͱ ͦͷΠϯλϓϦλ#㱺$ʹ෼཭͢Δ͜ͱ͕Մೳ
  15. Calculate the oldest ࠷೥௕ऀͷܭࢉ case class Person(name: String, age: Int)

    val p1 = Person("John", 30) val p2 = Person("Jack", 100)
  16. Calculate the oldest ͜Ε͸ςετ͢Δͷ͕೉͍͠ શ෦෭࡞༻Ͱग़ྗ͞Ε͍ͯΔͷͰࢀরಁաͰ͸ͳ͍ def calculateOldest(): Unit = {

    if(p1.age > p2.age) println(s"${p1.name} is oldest") else if(p2.age > p1.age) println(s"${p2.name} is oldest") else println("They are the same age") }
  17. Separation of concerns ؔ৺ࣄͷ෼཭ def calculateOldest(p1:Person, p2:Person):Unit = { if(p1.age

    > p2.age) println(s"${p1.name} is oldest") else if(p2.age > p1.age) println(s"${p2.name} is oldest") else println(s"They are the same age") }
  18. We can still split more ͞Βʹࡉ͔͘෼͚Δ def result(maybePerson:Option[Person]): Unit =

    maybePerson match { case Some(Person(name, age)) => println(s"${p.name} is oldest") case None => println("They are the same age") }
  19. A pure function core ͜ΕͰίΞ͕७ਮؔ਺ʹͳͬͨ def calculateOldest(p1: Person, p2: Person):

    Option[Person] def result(maybePerson: Option[Person]): String = maybePerson.map { case Person(name, age) => s"${name} is the oldest" } getOrElse "They are the same age" def combine(p1: Person, p2: Person): Unit = println(result(calculateOldest(p1,p2)))