Functional programming is one of the possible paradigm that we can use to write applications using Scala,
In this talk you will learn about:
* The benefits of using Functional programming approach
* The type classes in Scala
* And the common functional abstractions: semigroup, monoid, functor and monad
The challenge that the newcomers who were writing imperative code and want to start using Scala is: to change the way of thinking and reasoning about the code in a Functional way, in this talk I will go through the details and explain functional programming paradigm and how to work with type classes in Scala.
5. Paradigm
Is a style and a way of writing your programs.
Each programming language follow a programming
style.
パラダイムはプログラムを書く作法
6. Paradigm
Is a style and a way of writing your programs.
Each programming language follow a programming
style.
Scala combines
object-oriented and
functional programming.
Scalaは、オブジェクト指向プログラミングと関数型プログラミングを組み合わせたものです。
19. Referential transparency
When the function could be replaced by the result of
its evaluation without affecting the meaning of the
program.
def sum(a: Int, b: Int): Int = a + b
sum(2, 3) == 5
参照透過性は関数をその評価結果と置き換えても プログラムの振る舞いが変わらないこと
22. “A data types or a simple type is an attribute of data which tells
the compiler or interpreter how the programmer intends to use
the data.” -- Wikipedia
Data Types
データ型はデータ使用の意図を表す
23. “A data types or a simple type is an attribute of data which tells
the compiler or interpreter how the programmer intends to use
the data.” -- Wikipedia
Data Types
If it compiles, it
works!
コンパイルすれば動作します!
24. “Is a type formed by combining other types.” -- Wikipedia
ADT (Algebraic Data Type)
代数的データ型は型の組み合わせ
27. Product types
Setting(true, true)
Setting(false, true)
Setting(false, true)
Setting(false, false)
2 x 2 = 4
4 possible values
case class Setting(
audioEnabled: Boolean,
videoEnabled: Boolean
)
直積型
28. Sum types
sealed trait Color
case object Purple extends Color
case object Red extends Color
case object Yellow extends Color
case object Green extends Color
?
?
?
?
val color: Color = ???
直和型
29. Sum types
sealed trait Color
case object Purple extends Color
case object Red extends Color
case object Yellow extends Color
case object Green extends Color
?
?
?
?
val color: Color = ???
4 possible values
直和型
30. case class Form(
topic: String,
bgcolor: Color
)
Geometry
ADT
?
?
?
?
val form: Form =
Form(topic = ???, color = ???)
∞
31. sealed trait Topic
case object Art extends Topic
case object History extends Topic
case object Philosophy extends Topic
case object Geography extends Topic
ADT
32. case class Form(
topic: Topic,
bgcolor: Color
)
Geometry
ADT
?
?
?
?
val form: Form =
Form(topic = ???, color = ???)
?
?
?
33. case class Form(
topic: Topic,
bgcolor: Color
)
Geometry
ADT
?
?
?
?
val form: Form =
Form(topic = ???, color = ???)
?
?
?
4 x 4 = 16
16 possible values
34. sealed trait Option[+A]
case object None extends Option[Nothing]
case class Some[A](a: A) extends Option[A]
Parameterized ADT
val choice: Option[Boolean] =
???
Some(true)
Some(false)
None
パラメータ化された代数的データ型
35. sealed trait Option[+A]
case object None extends Option[Nothing]
case class Some[A](a: A) extends Option[A]
Parameterized ADT
val choice: Option[Int] =
???
Some(1)
Some(157)
None
Some(2)
Some(3)
Some(4)
Some(5)
Some(6)
Some(7)
Some(8)
Some(158)
Some(159)
Some(845)
Some(880)
Some(8810)
Some(81945)
Some(819447)
Some(36841840)
パラメータ化された代数的データ型
36. FP is the practice of composing programs using pure functions.
Functions
は純粋関数を用いてプログラムを書くための方法
37. A function takes data as an input and returns a data as an
output
Functions
def isPositive(n: Int): Boolean = n > 0
関数はデータを受け取りデータを返す
38. A function could be defined:
● As a data type.
First class functions
type Predicate = Int => Boolean
関数そのものもデータ型
39. A function could be defined:
● As a data type.
● Using a literal syntax.
First class functions
(n: Int) => n > 0
関数リテラル構文を用いて定義できる
40. Higher order functions accept other functions as input and/or return
functions as output.
Higher-order functions
高階関数は別の関数を受け取るか 関数を戻り値として返す
41. Higher order functions accept other functions as input and/or return
functions as output.
Higher-order functions
def checkOption(option: Option[Int], p: Int => Boolean): Boolean =
option match {
case Some(v) if p(v) => true
case _ => false
}
42. Higher order functions accept other functions as input and/or return
functions as output.
Higher-order functions
def checkOption(option: Option[Int], p: Int => Boolean): Boolean =
option match {
case Some(v) if p(v) => true
case _ => false
}
val isPositive: Int => Boolean = n => n > 0
checkOption(Some(14), isPositive)
43. Higher order functions accept other functions as input and/or return
functions as output.
Higher-order functions
def checkOption(option: Option[Int], p: Int => Boolean): Boolean =
option match {
case Some(v) if p(v) => true
case _ => false
}
val isPositive: Int => Boolean = _ > 0
checkOption(Some(14), isPositive)
44. Higher order functions accept other functions as input and/or return
functions as output.
Higher-order functions
def checkOption(option: Option[Int], p: Int => Boolean): Boolean =
option match {
case Some(v) if p(v) => true
case _ => false
}
checkOption(Some(14), n => n > 0)
45. Higher order functions accept other functions as input and/or return
functions as output.
Higher-order functions
def checkOption(option: Option[Int], p: Int => Boolean): Boolean =
option match {
case Some(v) if p(v) => true
case _ => false
}
checkOption(Some(14), _ > 0)
47. Type class
Is a way to define certain operations for a given type..
A type class instance for a given type provides an
implementation for these operations.
型に応じた演算を定義する方法 実装は特定の型クラスのインスタンスで定義される
59. Type class
trait Translator[A] {
def translate(
text: A,
from: Language,
to: Language): A
}
object Translator {
def apply[A](implicit t: Translator[A]): Translator[A] = t
}
型クラス
60. Polymorphic program using context bounds
def program[A: Translator] =
for {
message <- consumeMessages
(from, to) = detectLanguage(message)
newMsg = Translator[A].translate(message,from,to)
_ <- send(newMsg)
} yield ()
型クラス
62. Type class instances
implicit val discordTranslator = new Translator[DiscordMessage] { … }
implicit val stringTranslator = new Translator[String] { … }
implicit val documentTranslator = new Translator[Document] { … }
implicit val audioTranslator = new Translator[Audio] { … }
program[DiscordMessage]
program[String]
program[Document]
program[Audio]
型クラスのインスタンス
76. The identity law
def identity[A](a: A): A = a
//REMINDER: def map[A, B](f: A => B): F[A] => F[B]
map(identity) == identity
Identity
composition ?
Laws
単位元
77. trait Function1[-B, +C] {
def apply(b: B): C
def compose[A](g: A => B): A => C = a => apply(g(a))
}
Identity
composition
Laws
The compose function
合成関数
78. trait Function1[-B, +C] {
def apply(b: B): C
def compose[A](g: A => B): A => C = a => apply(g(a))
}
f: A => B
g: B => C
h: A => C
h = a => g(f(a))
===
g compose f
f ° g
The compose function
79. trait Function1[-B, +C] {
def apply(b: B): C
def compose[A](g: A => B): A => C = a => apply(g(a))
}
//REMINDER: def map[A, B](f: A => B): F[A] => F[B]
map(g compose f) == map(g) compose map(f)
Laws
The composition law
Identity
composition
80. implicit val optionFunctor: Functor[Option] = new Functor[Option]
{
override def map[A, B](f: A => B): Option[A] => Option[B] = {
case None => None
case Some(a) => Some(f(a))
}
}
Example for a Functor instance
Functor[Option]
ファンクター・インスタンスの例
81. implicit val optionFunctor: Functor[Option] = new Functor[Option]
{
override def map[A, B](f: A => B): Option[A] => Option[B] = {
case None => None
case Some(a) => Some(f(a))
}
}
Identity law for:
Functor[Option]
f: identity
f: A => A
None => None
Some(a) => Some(a)
identity
Functor[Option] の単位元
82. implicit val optionFunctor: Functor[Option] = new Functor[Option]
{
override def map[A, B](f: A => B): Option[A] => Option[B] = {
case None => None
case Some(a) => Some(f(a))
}
}
Composition law for:
Functor[Option]
Identity Law
map(identity)(Some(1)) == Some(1)
map(identity)(None) == None
def increment(i: Int): Int
def toString(i: Int): String
map(toString compose increment)
==
map(toString) compose map(increment)
Some(41)
Functor[Option] の合成律
83. implicit val optionFunctor: Functor[Option] = new Functor[Option]
{
override def map[A, B](f: A => B): Option[A] => Option[B] = {
case None => None
case Some(a) => Some(f(a))
}
}
Composition law for:
Functor[Option]
Identity Law
map(identity)(Some(1)) == Some(1)
map(identity)(None) == None
def increment(i: Int): Int
def toString(i: Int): String
map(toString compose increment)
==
map(toString) compose map(increment)
Some(41)
Some(“42”)
84. implicit val optionFunctor: Functor[Option] = new Functor[Option]
{
override def map[A, B](f: A => B): Option[A] => Option[B] = {
case None => None
case Some(a) => Some(f(a))
}
}
Composition law for:
Functor[Option]
Identity Law
map(identity)(Some(1)) == Some(1)
map(identity)(None) == None
def increment(i: Int): Int
def toString(i: Int): String
map(toString compose increment)
==
map(toString) compose map(increment)
Some(41)
Some(“42”)
Some(“42”)
85. Monad
trait Monad[F[_]] {
def map[A, B](f: A => B): F[A] => F[B]
def flatMap[A, B](f: A => F[B]): F[A] => F[B]
}
object Monad {
def apply[F[_]](implicit m: Monad[F]) : Monad[F] = m
}
Higher kinded type
モナド
92. You can checkout the Scala functional programming
libraries:
● Cats
Github: https://github.com/typelevel/cats
doc: https://typelevel.org/cats
● Scalaz: https://github.com/scalaz/scalaz
● Zio Prelude: https://github.com/zio/zio-prelude
Talks by:
● John De Goes and Adam Fraser: “Reimagining
Functional Type Classes”
● Jakub Kozlowski: “Fantastic Monads and where to
find them”
Resources
次へのリソース
94. CREDITS: This presentation template was created by Slidesgo, including icons by
Flaticon, and infographics & images by Freepik
THANKS!
Please keep this slide for attribution
@WiemZin
ご清聴ありがとうございました