Functional Programming For All - Scala Matsuri 2016

24
Functional Programming for All Zachary McCoy みんなの関数型プログラミング

Transcript of Functional Programming For All - Scala Matsuri 2016

Page 1: Functional Programming For All - Scala Matsuri 2016

Functional Programming for All

Zachary McCoy

みんなの関数型プログラミング

Page 2: Functional Programming For All - Scala Matsuri 2016

About Me

• Scala

• Iowa, USA

• twitter - @ZachAMcCoy

• email - [email protected]

Page 3: Functional Programming For All - Scala Matsuri 2016

What is Functional Programming?

• Programming… with functions

• Functions as the main abstraction

• Functions as first class values

「関数を用いたプログラミング」 「関数を主な抽象化の道具とする」「第一級値としての関数」

Page 4: Functional Programming For All - Scala Matsuri 2016

What is Functional Programming?

• Controlled side effects

• Restricts how we write programs, but not what we can express

「制御された副作用」 「表現の幅は狭めずに、プログラムの書き方を制約する」

Page 5: Functional Programming For All - Scala Matsuri 2016

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 は式を評価するのに対し、命令型は命令文から成る

Page 6: Functional Programming For All - Scala Matsuri 2016

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つもしくは複数の値に関する式 ドメインとコドメインの一意対応、イミュータブル

Page 7: Functional Programming For All - Scala Matsuri 2016

Pure Functions• No observable side-effects

• Anything that isn’t returning a result

• Mutation

• I/O

• Depends only on arguments or subset of

純粋関数は副作用を持たず、結果は引数にのみ依存する

Page 8: Functional Programming For All - Scala Matsuri 2016

Pure Functions

• Examples

• Hashing

• Arithmetic

純粋関数例:ハッシュ化、算術演算

Page 9: Functional Programming For All - Scala Matsuri 2016

Why does purity matter?

• Side effects cause order of evaluation to matter

• Only have to use local reasoning

• Composition and reusability

副作用は実行/評価順の考慮が必要になる、局所化、 合成と再利用性

Page 10: Functional Programming For All - Scala Matsuri 2016

Why does purity matter?

• Separate the computation over the input from how to obtain it

• Guarantees Referential Transparency

演算と入力を与える方法を分離、参照透過性を保証

Page 11: Functional Programming For All - Scala Matsuri 2016

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): 純粋な式がその値と置き換え可能なこと 関数が参照透過であるためには、入力も透過である必要がある

Page 12: Functional Programming For All - Scala Matsuri 2016

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"

置き換えモデル

Page 13: Functional Programming For All - Scala Matsuri 2016

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

参照透過性の形式化:式をその値と置き換えることができる プログラムの振る舞いは作用を含め変わってはいけない

Page 14: Functional Programming For All - Scala Matsuri 2016

Referential Transparency

• Mathematics!

• (2 * 2 = 4)

• Returning errors as values, rather than side effecting

参照透過性は数学! エラーは、副作用ではなく、値で返す

Page 15: Functional Programming For All - Scala Matsuri 2016

How does this tie together?

• Pure functions enable Referential Transparency

• RT enables the Substitution model and Equational Reasoning

• Pure functions are a huge gain!

純粋関数 ⇒ 参照透過性 ⇒ 置き換えモデル&等式推論 純粋関数 ⇒ ウマー

Page 16: Functional Programming For All - Scala Matsuri 2016

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 は参照透過性を強制しないため、自前での対応が必要

Page 17: Functional Programming For All - Scala Matsuri 2016

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 に分離することが可能

Page 18: Functional Programming For All - Scala Matsuri 2016

Calculate the oldest

最年長者の計算

case class Person(name: String, age: Int)

val p1 = Person("John", 30) val p2 = Person("Jack", 100)

Page 19: Functional Programming For All - Scala Matsuri 2016

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") }

Page 20: Functional Programming For All - Scala Matsuri 2016

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") }

Page 21: Functional Programming For All - Scala Matsuri 2016

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

Page 22: Functional Programming For All - Scala Matsuri 2016

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") }

Page 23: Functional Programming For All - Scala Matsuri 2016

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)))

Page 24: Functional Programming For All - Scala Matsuri 2016

We’re Hiring!

[email protected]

一緒に働きませんか?