KEMBAR78
Functional Programming For All - Scala Matsuri 2016 | PDF
Functional
Programming for All
Zachary McCoy
みんなの関数型プログラミング
About Me
• Scala
• Iowa, USA
• twitter - @ZachAMcCoy
• email - zach.mccoy@banno.com
What is Functional
Programming?
• Programming… with functions
• Functions as the main abstraction
• Functions as first class values
「関数を用いたプログラミング」
「関数を主な抽象化の道具とする」「第一級値としての関数」
What is Functional
Programming?
• Controlled side effects
• Restricts how we write programs, but not what we
can express
「制御された副作用」
「表現の幅は狭めずに、プログラムの書き方を制約する」
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
中核は純粋関数でその外側の層で副作用が実行される
FP は式を評価するのに対し、命令型は命令文から成る
What is a function?
• An expression involving one or more variables
• Domain and Co-Domain
• Unique mapping from D -> CD
• Immutability, produces something new
関数とは1つもしくは複数の値に関する式
ドメインとコドメインの一意対応、イミュータブル
Pure Functions
• No observable side-effects
• Anything that isn’t returning a result
• Mutation
• I/O
• Depends only on arguments or subset of
純粋関数は副作用を持たず、結果は引数にのみ依存する
Pure Functions
• Examples
• Hashing
• Arithmetic
純粋関数例:ハッシュ化、算術演算
Why does purity matter?
• Side effects cause order of evaluation to matter
• Only have to use local reasoning
• Composition and reusability
副作用は実行/評価順の考慮が必要になる、局所化、
合成と再利用性
Why does purity matter?
• Separate the computation over the input from how
to obtain it
• Guarantees Referential Transparency
演算と入力を与える方法を分離、参照透過性を保証
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
参照透過性 (RT): 純粋な式がその値と置き換え可能なこと
関数が参照透過であるためには、入力も透過である必要がある
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"

置き換えモデル
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
参照透過性の形式化:式をその値と置き換えることができる
プログラムの振る舞いは作用を含め変わってはいけない
Referential Transparency
• Mathematics!
• (2 * 2 = 4)
• Returning errors as values, rather than side
effecting
参照透過性は数学!
エラーは、副作用ではなく、値で返す
How does this tie together?
• Pure functions enable Referential Transparency
• RT enables the Substitution model and Equational
Reasoning
• Pure functions are a huge gain!
純粋関数 参照透過性 置き換えモデル&等式推論
純粋関数 ウマー
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
Scala は参照透過性を強制しないため、自前での対応が必要
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
純粋でない関数 A C は、純粋関数 A B と
そのインタプリタ B C に分離することが可能
Calculate the oldest
最年長者の計算
case class Person(name: String, age: Int)
val p1 = Person("John", 30)
val p2 = Person("Jack", 100)
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")
}
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")
}
Return values
戻り値を使うことでテストしやすくなった
def calculateOldest(p1: Person, p2: Person):
Option[Person] =
if(p1.age > p2.age)
Some(p1)
else if(p2.age > p1.age)
Some(p2)
else
None
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")
}
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)))
We’re Hiring!
zach.mccoy@banno.com
一緒に働きませんか?

Functional Programming For All - Scala Matsuri 2016

  • 1.
    Functional Programming for All ZacharyMcCoy みんなの関数型プログラミング
  • 2.
    About Me • Scala •Iowa, USA • twitter - @ZachAMcCoy • email - zach.mccoy@banno.com
  • 3.
    What is Functional Programming? •Programming… with functions • Functions as the main abstraction • Functions as first class values 「関数を用いたプログラミング」 「関数を主な抽象化の道具とする」「第一級値としての関数」
  • 4.
    What is Functional Programming? •Controlled side effects • Restricts how we write programs, but not what we can express 「制御された副作用」 「表現の幅は狭めずに、プログラムの書き方を制約する」
  • 5.
    Functional Programming • Purefunctional 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 中核は純粋関数でその外側の層で副作用が実行される FP は式を評価するのに対し、命令型は命令文から成る
  • 6.
    What is afunction? • An expression involving one or more variables • Domain and Co-Domain • Unique mapping from D -> CD • Immutability, produces something new 関数とは1つもしくは複数の値に関する式 ドメインとコドメインの一意対応、イミュータブル
  • 7.
    Pure Functions • Noobservable side-effects • Anything that isn’t returning a result • Mutation • I/O • Depends only on arguments or subset of 純粋関数は副作用を持たず、結果は引数にのみ依存する
  • 8.
    Pure Functions • Examples •Hashing • Arithmetic 純粋関数例:ハッシュ化、算術演算
  • 9.
    Why does puritymatter? • Side effects cause order of evaluation to matter • Only have to use local reasoning • Composition and reusability 副作用は実行/評価順の考慮が必要になる、局所化、 合成と再利用性
  • 10.
    Why does puritymatter? • Separate the computation over the input from how to obtain it • Guarantees Referential Transparency 演算と入力を与える方法を分離、参照透過性を保証
  • 11.
    Referential Transparency • Anexpression 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 参照透過性 (RT): 純粋な式がその値と置き換え可能なこと 関数が参照透過であるためには、入力も透過である必要がある
  • 12.
    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" 置き換えモデル
  • 13.
    Formalize Referential Transparency • Anexpression, 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 参照透過性の形式化:式をその値と置き換えることができる プログラムの振る舞いは作用を含め変わってはいけない
  • 14.
    Referential Transparency • Mathematics! •(2 * 2 = 4) • Returning errors as values, rather than side effecting 参照透過性は数学! エラーは、副作用ではなく、値で返す
  • 15.
    How does thistie together? • Pure functions enable Referential Transparency • RT enables the Substitution model and Equational Reasoning • Pure functions are a huge gain! 純粋関数 参照透過性 置き換えモデル&等式推論 純粋関数 ウマー
  • 16.
    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 Scala は参照透過性を強制しないため、自前での対応が必要
  • 17.
    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 純粋でない関数 A C は、純粋関数 A B と そのインタプリタ B C に分離することが可能
  • 18.
    Calculate the oldest 最年長者の計算 caseclass Person(name: String, age: Int) val p1 = Person("John", 30) val p2 = Person("Jack", 100)
  • 19.
    Calculate the oldest これはテストするのが難しい 全部副作用で出力されているので参照透過ではない defcalculateOldest(): 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") }
  • 20.
    Separation of concerns 関心事の分離 defcalculateOldest(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") }
  • 21.
    Return values 戻り値を使うことでテストしやすくなった def calculateOldest(p1:Person, p2: Person): Option[Person] = if(p1.age > p2.age) Some(p1) else if(p2.age > p1.age) Some(p2) else None
  • 22.
    We can stillsplit 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") }
  • 23.
    A pure functioncore これでコアが純粋関数になった 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)))
  • 24.