SlideShare una empresa de Scribd logo
1 de 76
Descargar para leer sin conexión
関数型プログラミング
2014-05-11 at ゆかむ勉強会
Suguru Hamazaki
Introduction to Scala Functional Programming
入�門
ご説明内容
Agenda
Scalaって?
関数型プログラミ
ングって?
ステートマシンをどう
やって実装するの?
もっと抽象化
できるよ!
便利な
ライブラリーがあるよ!
プログラミング言語
Scala Programming Language
オブジェクト指向と
関数型の融合
Have the best of both worlds.
Construct elegant class hierarchies
for maximum code reuse and
extensibility, implement their behavior
using higher-order functions. Or
anything in-between.
— from http://www.scala-lang.org/
Object-Oriented Meets Functional
But …
パラダイムシフトは難しい
A paradigm shift is difficult
関数型プログラミング
Functional Programming
純粋関数
Pure Function
純粋関数
Pure Function
• 関数の評価結果が引数の値のみに
よって決まり、同じ値を与えると
常に同じ値の結果を返す
• 関数の評価によって、観測可能な
副作用が発生しない
f
x y
副作用の例Side effects examples
• 変数に再代入する
• データの構造を破壊的に変更する
• オブジェクトのフィールドに値をセットする
• 例外を投げる、エラー時に終了する
• コンソールに出力する、ユーザー入力を読む
• ファイルを読み書きする
• スクリーンに描画する
Variable reassigning
Destructive mutation
Setting field values
Throwing exceptions or stopping at failure
Console output or reading user input
File I/O
Displaying to screen
純粋関数プログラムを書く
Write programs using only
pure functions
のみで
えっ?
コインのモデル
A coin model
head tail
flip
flip
stay stay
オブジェクト指向的コイン
case class OoCoin(private var head: Boolean) {	
def flip() = { head = !head }	
def stay() = {} // do nothing	
def get = head	
}
Object-Oriented Coin
オブジェクト指向的コイン
case class OoCoin(private var head: Boolean) {	
def flip() = { head = !head }	
def stay() = {} // do nothing	
def get = head	
}
var (variable) で宣言し
たフィールドに再代入
Object-Oriented Coin
val c = OoCoin(true)	
c.flip()	
c.stay()	
c.flip()	
println("Showing a head? " + c.get)
参照透過性
Referential Transparency
ある式の中で、その式の
値を変えることなく、
等しいもの同士を 置換できること
val a = 5	
sumOfSquares(a + 1, a * 2)
def square(i: Int) = i * i 	
def sumOfSquares(i1: Int, i2: Int) =	
square(i1) + square(i2)
val a = 5	
sumOfSquares(a + 1, a * 2)
def square(i: Int) = i * i 	
def sumOfSquares(i1: Int, i2: Int) =	
square(i1) + square(i2)	
純粋な関数
val a = 5	
sumOfSquares(a + 1, a * 2)
def square(i: Int) = i * i 	
def sumOfSquares(i1: Int, i2: Int) =	
square(i1) + square(i2)	
純粋な関数
再代入できない val
置換モデル
sumOfSquares(a + 1, a * 2)	
sumOfSquares(5 + 1, 5 * 2)	
sumOfSquares(6, 10)	
square(6) + square(10)	
(6 * 6) + (10 * 10)	
36 + 100	
136
Substitution Model
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html
再び、コインの例を見てみる
OK, let’s go back to the coin model
val c = OoCoin(true)	
c.flip()	
c.stay()	
c.flip()	
println("Showing a head? " + c.get)
val c = OoCoin(true)	
c.flip()	
c.stay()	
c.flip()	
println("Showing a head? " + c.get)
mutable なデータ構造と
非純粋関数
val c = OoCoin(true)	
c.flip()	
c.stay()	
c.flip()	
println("Showing a head? " + c.get)
mutable なデータ構造と
非純粋関数
参照透過性は?
不変なコインと
純粋関数を使う
Use immutable coins
and pure functions
case class Coin(head: Boolean)	
!
object Coin1 {	
def flip(c: Coin) = Coin(!c.head)	
def stay(c: Coin) = c	
}
case class Coin(head: Boolean)	
!
object Coin1 {	
def flip(c: Coin) = Coin(!c.head)	
def stay(c: Coin) = c	
}	
case class のフィー
ルドはデフォルトで
immutable
case class Coin(head: Boolean)	
!
object Coin1 {	
def flip(c: Coin) = Coin(!c.head)	
def stay(c: Coin) = c	
}	
case class のフィー
ルドはデフォルトで
immutable
受け取ったCoinは変更せず、新しいCoinを生成
val c0 = Coin(true)	
val c1 = flip(c0)	
val c2 = stay(c1)	
val c3 = flip(c2)	
println("Showing a head? " + c3.head)
val c0 = Coin(true)	
val c1 = flip(c0)	
val c2 = stay(c1)	
val c3 = flip(c2)	
println("Showing a head? " + c3.head)
コインの 操作
クラスで表現してみる
を
Express an ‘Action’ of a coin with a class
case class CoinAction(action: Coin => Coin) extends (Coin => Coin) {	
def apply(c: Coin) = action(c)	
def +(next: CoinAction): CoinAction = CoinAction { c0 =>	
val c1 = action(c0)	
next(c1)	
}	
}
case class CoinAction(action: Coin => Coin) extends (Coin => Coin) {	
def apply(c: Coin) = action(c)	
def +(next: CoinAction): CoinAction = CoinAction { c0 =>	
val c1 = action(c0)	
next(c1)	
}	
}
Coinの状態を遷移さ
せる関数をラップ
case class CoinAction(action: Coin => Coin) extends (Coin => Coin) {	
def apply(c: Coin) = action(c)	
def +(next: CoinAction): CoinAction = CoinAction { c0 =>	
val c1 = action(c0)	
next(c1)	
}	
}
Coinの状態を遷移さ
せる関数をラップ 自身も関数として扱える
case class CoinAction(action: Coin => Coin) extends (Coin => Coin) {	
def apply(c: Coin) = action(c)	
def +(next: CoinAction): CoinAction = CoinAction { c0 =>	
val c1 = action(c0)	
next(c1)	
}	
}
Coinの状態を遷移さ
せる関数をラップ 自身も関数として扱える
「コインを受け取った時に、自
身の action を実行してから、次
の操作を実行する」という関数
case class CoinAction(action: Coin => Coin) extends (Coin => Coin) {	
def apply(c: Coin) = action(c)	
def +(next: CoinAction): CoinAction = CoinAction { c0 =>	
val c1 = action(c0)	
next(c1)	
}	
}
Coinの状態を遷移さ
せる関数をラップ 自身も関数として扱える
関数として呼び出された際に、
ラップした関数を実行
「コインを受け取った時に、自
身の action を実行してから、次
の操作を実行する」という関数
First class Functions
• 引数として渡せる
• 戻り値として返せる
• 変数に代入できる
val flip = CoinAction(c => Coin(!c.head))	
val stay = CoinAction(c => c)
flip, stay を CoinAction の
インスタンスとして定義
val action = flip + stay + flip	
val c = action(Coin(true))	
println("Showing a head? " + c.head)
+() メソッドで操作を
1つにまとめる
val action = flip + stay + flip	
val c = action(Coin(true))	
println("Showing a head? " + c.head)
+() メソッドで操作を
1つにまとめる
でも、途中の結果も
欲しい時は?
case class CoinAction[A](action: Coin => (Coin, A))	
extends (Coin => (Coin, A)) {	
def apply(c: Coin) = action(c)	
def +[B](next: CoinAction[B]): CoinAction[B] =	
flatMap(_ => next)	
def map[B](f: A => B): CoinAction[B] = CoinAction { c0 =>	
val (c1, a) = apply(c0)	
(c1, f(a))	
}	
def flatMap[B](f: A => CoinAction[B]): CoinAction[B] =	
CoinAction { c0 =>	
val (c1, a) = apply(c0)	
f(a)(c1)	
}	
}
case class CoinAction[A](action: Coin => (Coin, A))	
extends (Coin => (Coin, A)) {	
def apply(c: Coin) = action(c)	
def +[B](next: CoinAction[B]): CoinAction[B] =	
flatMap(_ => next)	
def map[B](f: A => B): CoinAction[B] = CoinAction { c0 =>	
val (c1, a) = apply(c0)	
(c1, f(a))	
}	
def flatMap[B](f: A => CoinAction[B]): CoinAction[B] =	
CoinAction { c0 =>	
val (c1, a) = apply(c0)	
f(a)(c1)	
}	
}
Coinと一緒に任意の型の結果を返す
case class CoinAction[A](action: Coin => (Coin, A))	
extends (Coin => (Coin, A)) {	
def apply(c: Coin) = action(c)	
def +[B](next: CoinAction[B]): CoinAction[B] =	
flatMap(_ => next)	
def map[B](f: A => B): CoinAction[B] = CoinAction { c0 =>	
val (c1, a) = apply(c0)	
(c1, f(a))	
}	
def flatMap[B](f: A => CoinAction[B]): CoinAction[B] =	
CoinAction { c0 =>	
val (c1, a) = apply(c0)	
f(a)(c1)	
}	
}
Coinと一緒に任意の型の結果を返す
遷移した結果を
任意の型に変換する
case class CoinAction[A](action: Coin => (Coin, A))	
extends (Coin => (Coin, A)) {	
def apply(c: Coin) = action(c)	
def +[B](next: CoinAction[B]): CoinAction[B] =	
flatMap(_ => next)	
def map[B](f: A => B): CoinAction[B] = CoinAction { c0 =>	
val (c1, a) = apply(c0)	
(c1, f(a))	
}	
def flatMap[B](f: A => CoinAction[B]): CoinAction[B] =	
CoinAction { c0 =>	
val (c1, a) = apply(c0)	
f(a)(c1)	
}	
}
Coinと一緒に任意の型の結果を返す
遷移した結果を
任意の型に変換する
次の操作と組み合わせる。ただし、
前の結果を元に次の操作を生成する
関数として受け取る
val flip = CoinAction { c =>	
val head = !c.head	
(Coin(head), head)	
}	
val stay = CoinAction(c => (c, c.head))
val flip = CoinAction { c =>	
val head = !c.head	
(Coin(head), head)	
}	
val stay = CoinAction(c => (c, c.head))
Coinと一緒に
Boolean 型の結果を
返す
val action =	
flip.flatMap { _ =>	
stay.flatMap { _ =>	
flip	
}	
}	
val (c, _) = action(Coin(true))	
println("Showing a head? " + c.head)
val action =	
flip.flatMap { _ =>	
stay.flatMap { _ =>	
flip	
}	
}	
val (c, _) = action(Coin(true))	
println("Showing a head? " + c.head)
flip + stay + flip と
同様のコード
val action =	
flip.flatMap { _ =>	
stay.flatMap { _ =>	
flip	
}	
}	
val (c, _) = action(Coin(true))	
println("Showing a head? " + c.head)
flip + stay + flip と
同様のコード
ただし、単なる CoinActionではなく、CoinAction を返
す関数を渡している
val action =	
flip.flatMap { b1 =>	
stay.flatMap { _ =>	
flip.map { b3 =>	
(b1, b3)	
}	
}	
}	
val (_, (b1, b3)) = action(Coin(true))	
println("1st occurrence is a head? " + b1)	
println("3rd occurrence is a head? " + b3)
val action =	
flip.flatMap { b1 =>	
stay.flatMap { _ =>	
flip.map { b3 =>	
(b1, b3)	
}	
}	
}	
val (_, (b1, b3)) = action(Coin(true))	
println("1st occurrence is a head? " + b1)	
println("3rd occurrence is a head? " + b3)
結果が Tuple になるよう
map() で変換
val action =	
flip.flatMap { b1 =>	
stay.flatMap { _ =>	
flip.map { b3 =>	
(b1, b3)	
}	
}	
}	
val (_, (b1, b3)) = action(Coin(true))	
println("1st occurrence is a head? " + b1)	
println("3rd occurrence is a head? " + b3)
結果が Tuple になるよう
map() で変換
flatMap() が受けるのは、今の操作の結果から、次回以降の操作を作る関数。
val action =	
flip.flatMap { b1 =>	
stay.flatMap { _ =>	
flip.map { b3 =>	
(b1, b3)	
}	
}	
}	
val (_, (b1, b3)) = action(Coin(true))	
println("1st occurrence is a head? " + b1)	
println("3rd occurrence is a head? " + b3)
結果が Tuple になるよう
map() で変換
flatMap() が受けるのは、今の操作の結果から、次回以降の操作を作る関数。
なので、b1, b3 がネスト
した内部ブロックで利用
できる
val action = for {	
b1 <- flip	
_ <- stay	
b3 <- flip	
} yield (b1, b3)	
val (_, (b1, b3)) = action(Coin(true))	
println("1st occurrence is a head? " + b1)	
println("3rd occurrence is a head? " + b3)
map(), flatMap() があれば、for-comprehension が使える
val action = for {	
s1 <- flip.map(b1 => "1st occurrence is a head? " + b1)	
_ <- stay	
s3 <- flip.map(b3 => "3rd occurrence is a head? " + b3)	
} yield (s1 + "n" + s3)	
val (_, s) = action(Coin(true))	
println(s)
val action = for {	
s1 <- flip.map(b1 => "1st occurrence is a head? " + b1)	
_ <- stay	
s3 <- flip.map(b3 => "3rd occurrence is a head? " + b3)	
} yield (s1 + "n" + s3)	
val (_, s) = action(Coin(true))	
println(s)
この時点で、
CoinAction[Boolean] を
CoinAction[String] に変換して
しまう
CoinActionを抽象化
case class CoinAction[A](action: Coin => (Coin, A))	
extends (Coin => (Coin, A)) {	
def apply(c: Coin) = action(c)	
def +[B](next: CoinAction[B]): CoinAction[B] =	
flatMap(_ => next)	
def map[B](f: A => B): CoinAction[B] = CoinAction { c0 =>	
val (c1, a) = apply(c0)	
(c1, f(a))	
}	
def flatMap[B](f: A => CoinAction[B]): CoinAction[B] =	
CoinAction { c0 =>	
val (c1, a) = apply(c0)	
f(a)(c1)	
}	
}
case class CoinAction[A](action: Coin => (Coin, A))	
extends (Coin => (Coin, A)) {	
def apply(c: Coin) = action(c)	
def +[B](next: CoinAction[B]): CoinAction[B] =	
flatMap(_ => next)	
def map[B](f: A => B): CoinAction[B] = CoinAction { c0 =>	
val (c1, a) = apply(c0)	
(c1, f(a))	
}	
def flatMap[B](f: A => CoinAction[B]): CoinAction[B] =	
CoinAction { c0 =>	
val (c1, a) = apply(c0)	
f(a)(c1)	
}	
}
Coin のメソッドをどこ
からも呼び出してない
case class State[S, +A](run: S => (S, A)) {	
def map[B](f: A => B): State[S, B] =	
State { s =>	
val (s2, a) = run(s)	
(s2, f(a))	
}	
def flatMap[B](f: A => State[S, B]): State[S, B] =	
State { s =>	
val (s2, a) = run(s)	
f(a).run(s2)	
}	
}
Coin を型パラメーター
S として抽象化
Functional Programming in Scala
http://www.manning.com/bjarnason/ より抜粋、一部改変
type CoinAction[A] = State[Coin, A]	
val flip: CoinAction[Boolean] = State { c =>	
val head = !c.head	
(Coin(head), head)	
}	
val stay: CoinAction[Boolean] = State(c => (c, c.head))
CoinAction を type alias
として定義
先ほどと同じように
使えます
Wait …
それ
でできるよ
Scalaz
Scalaz
Scalaz provides purely functional
data structures to complement those
from the Scala standard library.
— from http://typelevel.org/projects/scalaz/
import scalaz.State	
type CoinAction[A] = State[Coin, A]
scalaz の State を使う
先ほどと同じように
使えます
まとめ
Summary
ScalaはOOとFPがミックスした
マルチパラダイム言語
関数型プログラミングでは
純粋関数を使う
状態遷移を表わす
CoinAction を作り、ステート
マシンを実装した
CoinAction を
State として抽象化
Scalaz の State
を紹介
詳しい解説ドキュメント&
完全なソースコードはこちら
https://github.com/hamazy/scala-fp-calisthenics
Q&A
Image Credits

Más contenido relacionado

Destacado

Gradle 3.0: Unleash the Daemon!
Gradle 3.0: Unleash the Daemon!Gradle 3.0: Unleash the Daemon!
Gradle 3.0: Unleash the Daemon!Eric Wendelin
 
Introduction to functional programming using Ocaml
Introduction to functional programming using OcamlIntroduction to functional programming using Ocaml
Introduction to functional programming using Ocamlpramode_ce
 
Groovy Grails DevJam Jam Session
Groovy Grails DevJam Jam SessionGroovy Grails DevJam Jam Session
Groovy Grails DevJam Jam SessionMike Hugo
 
Scala: functional programming for the imperative mind
Scala: functional programming for the imperative mindScala: functional programming for the imperative mind
Scala: functional programming for the imperative mindSander Mak (@Sander_Mak)
 
類別的繼承
類別的繼承類別的繼承
類別的繼承Justin Lin
 
Java Tutorial:Learn Java in 06:00:00
Java Tutorial:Learn Java in 06:00:00Java Tutorial:Learn Java in 06:00:00
Java Tutorial:Learn Java in 06:00:00Justin Lin
 
Advanced Functional Programming in Scala
Advanced Functional Programming in ScalaAdvanced Functional Programming in Scala
Advanced Functional Programming in ScalaPatrick Nicolas
 
Gradle a new Generation Build Tool
Gradle a new Generation Build ToolGradle a new Generation Build Tool
Gradle a new Generation Build ToolShinya Mochida
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scalapramode_ce
 

Destacado (12)

Fpga
FpgaFpga
Fpga
 
Gradle 3.0: Unleash the Daemon!
Gradle 3.0: Unleash the Daemon!Gradle 3.0: Unleash the Daemon!
Gradle 3.0: Unleash the Daemon!
 
Spray intro
Spray introSpray intro
Spray intro
 
Introduction to functional programming using Ocaml
Introduction to functional programming using OcamlIntroduction to functional programming using Ocaml
Introduction to functional programming using Ocaml
 
Groovy Grails DevJam Jam Session
Groovy Grails DevJam Jam SessionGroovy Grails DevJam Jam Session
Groovy Grails DevJam Jam Session
 
Scala: functional programming for the imperative mind
Scala: functional programming for the imperative mindScala: functional programming for the imperative mind
Scala: functional programming for the imperative mind
 
類別的繼承
類別的繼承類別的繼承
類別的繼承
 
資料結構
資料結構資料結構
資料結構
 
Java Tutorial:Learn Java in 06:00:00
Java Tutorial:Learn Java in 06:00:00Java Tutorial:Learn Java in 06:00:00
Java Tutorial:Learn Java in 06:00:00
 
Advanced Functional Programming in Scala
Advanced Functional Programming in ScalaAdvanced Functional Programming in Scala
Advanced Functional Programming in Scala
 
Gradle a new Generation Build Tool
Gradle a new Generation Build ToolGradle a new Generation Build Tool
Gradle a new Generation Build Tool
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 

Similar a Introduction to Scala Functional Programming

Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
今さら始めるCoffeeScript
今さら始めるCoffeeScript今さら始めるCoffeeScript
今さら始めるCoffeeScriptAshitaba YOSHIOKA
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
モナドをつくろう
モナドをつくろうモナドをつくろう
モナドをつくろうdico_leque
 
なぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriなぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriYuta Okamoto
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8y_taka_23
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話bleis tift
 
Guide for Swift and Viewer app
Guide for Swift and Viewer appGuide for Swift and Viewer app
Guide for Swift and Viewer appShintaro Kaneko
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミングOuka Yuka
 
Why Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriWhy Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriYuta Okamoto
 
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングTanUkkii
 
第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016kyoto university
 
SwiftでRiemann球面を扱う
SwiftでRiemann球面を扱うSwiftでRiemann球面を扱う
SwiftでRiemann球面を扱うhayato iida
 
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsShogo Sensui
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalazTomoharu ASAMI
 

Similar a Introduction to Scala Functional Programming (20)

Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
今さら始めるCoffeeScript
今さら始めるCoffeeScript今さら始めるCoffeeScript
今さら始めるCoffeeScript
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
モナドをつくろう
モナドをつくろうモナドをつくろう
モナドをつくろう
 
なぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriなぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuri
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
 
Guide for Swift and Viewer app
Guide for Swift and Viewer appGuide for Swift and Viewer app
Guide for Swift and Viewer app
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
 
Why Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriWhy Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuri
 
Actor&stm
Actor&stmActor&stm
Actor&stm
 
Coqでsprintf
CoqでsprintfCoqでsprintf
Coqでsprintf
 
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
 
第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016
 
Coqでsprintf
CoqでsprintfCoqでsprintf
Coqでsprintf
 
SwiftでRiemann球面を扱う
SwiftでRiemann球面を扱うSwiftでRiemann球面を扱う
SwiftでRiemann球面を扱う
 
Haskell超入門 Part.1
Haskell超入門 Part.1Haskell超入門 Part.1
Haskell超入門 Part.1
 
cp-9. 再帰関数
cp-9. 再帰関数cp-9. 再帰関数
cp-9. 再帰関数
 
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalaz
 

Introduction to Scala Functional Programming