8. 関数型の紹介
関数型の基礎
関数型言語において, 数学的な意味での関数を扱う.
x! : N → N
{
1
(x = 0)
x! =
x · (x − 1)! (その他)
§
¤
def f a c t ( x : Long ) : Long = x match {
case 0 => 1
case _ => x * f a c t ( x − 1)
}
¦
¥
Daniel Perez
関数型言語
2013年12月20日
7 / 21
14. 関数型のフィーチャー
第一級関数
高階関数
関数は他の型と同じ扱いかたができる
関数を別の関数に渡すこともできる
§
¤
val l i s t = L i s t ( 1 , 2 , 3)
def square ( x : I n t ) = x * x
l i s t map square / / L i s t ( 1 , 4 , 9)
/ / postfixOps are l e f t a s s o c i a t i v e
l i s t map square foreach p r i n t l n / / 1n4 n9
/ / l i s t .map( square ) . foreach ( p r i n t l n )
¦
¥
Daniel Perez
関数型言語
2013年12月20日
11 / 21
16. 関数型のフィーチャー
第一級関数
カリー化
非カリー化の関数
f : (X × Y ) → Z
カリー化の関数
f : X → (Y → Z)
§
¤
def w i t h W r i t e r ( f i l e : F i l e ) ( block : B u f f e r e d W r i t e r =>
Unit ) = . . . .
w i t h W r i t e r ( new F i l e ( " foobar " ) ) { out => out w r i t e "
foobar " }
¦
¥
Daniel Perez
関数型言語
2013年12月20日
12 / 21
18. 関数型のフィーチャー
第一級関数
部分適用
関数が関数を返す
f : X → (Y → Z)
⇒∀ x ∈ X, f (x) ∈ Z Y
§
¤
def w i t h W r i t e r ( f i l e : F i l e ) ( block : B u f f e r e d W r i t e r =>
Unit ) = . . . .
val f o o W r i t e r = w i t h W r i t e r ( new F i l e ( " foo " ) )
f o o W r i t e r { out => out p r i n t l n " foobar " }
f o o W r i t e r { out => out p r i n t l n " barbaz " }
¦
¥
Daniel Perez
関数型言語
2013年12月20日
13 / 21
23. 関数型のフィーチャー
再帰
再帰の例
.
階乗
.
.
§
{
1
(x = 0)
x! =
x · (x − 1)! (その他)
¤
def f a c t ( x : Long ) : Long = x match {
case 0 => 1
case _ => x * f a c t ( x − 1)
}
¦
¥
Daniel Perez
関数型言語
2013年12月20日
15 / 21
24. 関数型のフィーチャー
再帰
再帰の例
.
drop関数
.
drop(2, [1, 2, 3, 4])= [3, 4]
{
{a1 , · · · , an }
(x = 0)
f (x, {a1 , · · · , an }) =
f ((x − 1), {a2 , · · · , an }) (x > 0)
.
Daniel Perez
関数型言語
2013年12月20日
16 / 21
25. 関数型のフィーチャー
再帰
再帰の例
.
drop関数
.
drop(2, [1, 2, 3, 4])= [3, 4]
{
{a1 , · · · , an }
(x = 0)
f (x, {a1 , · · · , an }) =
f ((x − 1), {a2 , · · · , an }) (x > 0)
.
§
¦
¤
def drop [ A ] ( n : I n t , l i s t : L i s t [ A ] ) : L i s t [ A ] = n match {
case 0 => l i s t
case _ => drop ( n − 1 , l i s t . t a i l )
Daniel Perez
関数型言語
2013年12月20日
¥
16 / 21
26. 関数型のフィーチャー
再帰
再帰の例
.
map関数
.
map(f, [1, 2, 3])= [f(1), f(2), f(3)]
S, T は任意の集合
X = {a1 , · · · , an } ⊂ S
.
m : TS × X → Y ⊂ T
{
∅
m(f, {a1 , · · · , an }) =
∪
{f (a1 )} m(f, {a2 , · · · , an })
Daniel Perez
関数型言語
(X = ∅)
(その他)
2013年12月20日
17 / 21
27. 関数型のフィーチャー
再帰
再帰の例
.
map関数
.
map(f, [1, 2, 3])= [f(1), f(2), f(3)]
S, T は任意の集合
X = {a1 , · · · , an } ⊂ S
m : TS × X → Y ⊂ T
{
∅
m(f, {a1 , · · · , an }) =
∪
{f (a1 )} m(f, {a2 , · · · , an })
.
§
(X = ∅)
(その他)
¤
def map[ A , B ] ( f : A => B , l i s t : L i s t [ A ] ) : L i s t [ B ] = l i s t match {
case N i l
=> N i l
case head : : t a i l => f ( head ) : : map( f , t a i l )
}
¦
¥
Daniel Perez
関数型言語
2013年12月20日
17 / 21
28. 関数型のフィーチャー
再帰
名前呼び (Call by name)
関数呼び出し時に結果まだ評価しなくて良い
関数内で始めて値を使う時に評価する
Daniel Perez
関数型言語
2013年12月20日
18 / 21
29. 関数型のフィーチャー
再帰
名前呼び (Call by name)
§
¦
関数呼び出し時に結果まだ評価しなくて良い
関数内で始めて値を使う時に評価する
¤
def f = { p r i n t l n ( " c a l l f " ) ; 1 }
Daniel Perez
関数型言語
¥
2013年12月20日
18 / 21
30. 関数型のフィーチャー
再帰
名前呼び (Call by name)
§
¦
§
関数呼び出し時に結果まだ評価しなくて良い
関数内で始めて値を使う時に評価する
¤
def f = { p r i n t l n ( " c a l l f " ) ; 1 }
def fByValue ( n : I n t ) = {
¥
¤
p r i n t l n ( " c a l l i n g fByValue " )
p r i n t l n ( s " x1 = $n" )
p r i n t l n ( s " x2 = $n" )
}
fByValue ( f )
¦
¥
Daniel Perez
関数型言語
2013年12月20日
18 / 21
31. 関数型のフィーチャー
再帰
名前呼び (Call by name)
§
¦
§
関数呼び出し時に結果まだ評価しなくて良い
関数内で始めて値を使う時に評価する
¤
def f = { p r i n t l n ( " c a l l f " ) ; 1 }
def fByValue ( n : I n t ) = {
¤§
p r i n t l n ( " c a l l i n g fByValue " )
p r i n t l n ( s " x1 = $n" )
p r i n t l n ( s " x2 = $n" )
def fByName ( n : => I n t ) = {
p r i n t l n ( " c a l l i n g fByName" )
p r i n t l n ( s " x1 = $n" )
p r i n t l n ( s " x2 = $n" )
}
fByValue ( f )
¦
}
fByName ( f )
¥¦
Daniel Perez
¥
¤
関数型言語
¥
2013年12月20日
18 / 21
32. 関数型のフィーチャー
再帰
名前呼び (Call by name)
§
¦
§
関数呼び出し時に結果まだ評価しなくて良い
関数内で始めて値を使う時に評価する
def fByValue ( n : I n t ) = {
¤§
p r i n t l n ( " c a l l i n g fByValue " )
p r i n t l n ( s " x1 = $n" )
p r i n t l n ( s " x2 = $n" )
call f
c a l l i n g fByValue
x1 = 1
x2 = 1
¦
¥
¤
def fByName ( n : => I n t ) = {
p r i n t l n ( " c a l l i n g fByName" )
p r i n t l n ( s " x1 = $n" )
p r i n t l n ( s " x2 = $n" )
}
fByValue ( f )
¦
§
¤
def f = { p r i n t l n ( " c a l l f " ) ; 1 }
}
fByName ( f )
¥¦
¤
¥
¥
Daniel Perez
関数型言語
2013年12月20日
18 / 21
33. 関数型のフィーチャー
再帰
名前呼び (Call by name)
§
¦
§
関数呼び出し時に結果まだ評価しなくて良い
関数内で始めて値を使う時に評価する
def fByValue ( n : I n t ) = {
¤§
p r i n t l n ( " c a l l i n g fByValue " )
p r i n t l n ( s " x1 = $n" )
p r i n t l n ( s " x2 = $n" )
call f
c a l l i n g fByValue
x1 = 1
x2 = 1
¦
def fByName ( n : => I n t ) = {
}
fByName ( f )
¥¦
¤§
¥¦
Daniel Perez
¥
¤
p r i n t l n ( " c a l l i n g fByName" )
p r i n t l n ( s " x1 = $n" )
p r i n t l n ( s " x2 = $n" )
}
fByValue ( f )
¦
§
¤
def f = { p r i n t l n ( " c a l l f " ) ; 1 }
関数型言語
c a l l i n g fByName
call f
x1 = 1
call f
x2 = 1
¥
¤
¥
2013年12月20日
18 / 21