たのしい高階関数

81

Upload: shinichi-kozake

Post on 21-May-2015

5.436 views

Category:

Technology


3 download

DESCRIPTION

第2回関数型勉強会 in 大阪 で使った資料です。

TRANSCRIPT

Page 1: たのしい高階関数
Page 2: たのしい高階関数

λλfunctionalfunctional

Page 3: たのしい高階関数

presented by presented by @s_kozake@s_kozake

Page 4: たのしい高階関数

map / filter / foldl / foldrmap / filter / foldl / foldr

Page 5: たのしい高階関数

in in

Page 6: たのしい高階関数

λλたのしい高階関数たのしい高階関数

発表をする資料をつくる資料をあきらめる

こわくないよこわくないよ

Page 7: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

目的目的本勉強会の趣旨

本セッションは高階関数入門です関数型言語の視野を拡げ、たのしく使っていくことを目的としております。

Page 8: たのしい高階関数

つまりですねつまりですね

Page 9: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

目的目的本勉強会の趣旨

本セッションは高階関数入門です関数型言語の視野を拡げ、たのしく使っていくことを目的としております。

Page 10: たのしい高階関数

大事なことなので大事なことなので2回いいました2回いいました

Page 11: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

注意事項注意事項

Page 12: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

関数型言語は怖いイメージがあるみたいですが

Page 13: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

当セッションはイージーモードです。当セッションはイージーモードです。

Page 14: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

ダメ。ゼッタイ。ダメ。ゼッタイ。

モナド / ファンクタ / 遅延評価 / 圏論 / 論証

「みんなやってる」なんて理由にならない

Page 15: たのしい高階関数

このようなこのような悲劇悲劇を繰り返さないためにもねを繰り返さないためにもね

プログラマたちは ぜんめつしました。

Page 16: たのしい高階関数

たのしくたのしく学びましょう~学びましょう~

Page 17: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

自己紹介自己紹介

Java Scala

★★☆

☆☆☆

Haskell ☆☆☆

アストルティア

Twitter@s_kozake

そろそろ Scala で仕事したいです。

Page 18: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?

高階関数を学ぶメリット

リストを扱う高階関数

まとめ

AgendaAgenda

Page 19: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?

高階関数を学ぶメリット

リストを扱う高階関数

まとめ

AgendaAgenda

Page 20: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?高階関数ってなに?

引数として関数を取ったり、引数として関数を取ったり、返り値として関数を返したりする関数返り値として関数を返したりする関数

関数型言語では、関数型言語では、関数がファーストクラスオブジェクト関数がファーストクラスオブジェクトとして扱える。として扱える。

Page 21: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?高階関数ってなに?

ファーストクラスオブジェクトとはファーストクラスオブジェクトとは

・無名のリテラルとして表現可能・無名のリテラルとして表現可能・変数に格納可能・変数に格納可能・データ構造への組み込みが可能・データ構造への組み込みが可能・プロシージャや関数のパラメータとして渡すことができる・プロシージャや関数のパラメータとして渡すことができる・プロシージャや関数の戻り値として返すことができる・プロシージャや関数の戻り値として返すことができる

Page 22: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?高階関数ってなに?

def twice(f:(Int => Int))(x:Int):Int = f(f(x))def twice(f:(Int => Int))(x:Int):Int = f(f(x))

Page 23: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

def twice(def twice(f:(Int => Int)f:(Int => Int)))(x:Int):Int(x:Int):Int = f(f(x)) = f(f(x))

高階関数ってなに?高階関数ってなに?

関数 関数 twicetwice ははIntInt 型の引数を受け取り型の引数を受け取り IntInt 型の値を返す関数型の値を返す関数 ffを受け取り、を受け取り、IntInt 型の引数を受け取り型の引数を受け取り IntInt 型の値を返す関数型の値を返す関数を返す関数を返す関数

Page 24: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

def twice(f:(Int => Int))(x:Int):Int = f(f(x))def twice(f:(Int => Int))(x:Int):Int = f(f(x))def add1(x:Int) = x + 1def add1(x:Int) = x + 1

> val add2 = twice(add1)(_)> val add2 = twice(add1)(_)add2: Int => Int = <function1>add2: Int => Int = <function1>

> add2(3)> add2(3)res1: Int = 5res1: Int = 5

高階関数ってなに?高階関数ってなに?

Page 25: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

def twice(f:(Int => Int))(x:Int):Int = f(f(x))def twice(f:(Int => Int))(x:Int):Int = f(f(x))def add1(x:Int) = x + 1def add1(x:Int) = x + 1

> val add2 = twice(add1)(_)> val add2 = twice(add1)(_)add2: Int => Int = <function1>add2: Int => Int = <function1>

> add2(3)> add2(3)res1: Int = 5res1: Int = 5

高階関数ってなに?高階関数ってなに?

IntInt 型の引数を受け取り型の引数を受け取りIntInt 型の値を返す関数型の値を返す関数

IntInt 型の引数を受け取り型の引数を受け取りIntInt 型の値を返す関数型の値を返す関数

Page 26: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?高階関数ってなに?

def twice(f:(Int => Int))(x:Int):Int = f(f(x))def twice(f:(Int => Int))(x:Int):Int = f(f(x))def add1(x:Int) = x + 1def add1(x:Int) = x + 1

> val add2 = twice(add1)(_)> val add2 = twice(add1)(_)add2: Int => Int = <function1>add2: Int => Int = <function1>

> add2(3) > add2(3) = twice(add1)(3) = add1(add1(3))= twice(add1)(3) = add1(add1(3))res1: Int = 5res1: Int = 5

Page 27: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?

高階関数を学ぶメリット

リストを扱う高階関数

まとめ

AgendaAgenda

Page 28: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

処理の再利用の行いやすさ処理の再利用の行いやすさ

パターンとしての高階関数パターンとしての高階関数

Page 29: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

処理の再利用の行いやすさ処理の再利用の行いやすさ

パターンとしての高階関数パターンとしての高階関数

Page 30: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

関数関数 aa

個別処理

共通処理

共通処理

例えば、ある関数例えば、ある関数 aaの大部分がの大部分が共通処理で、一部が個別処理の場合共通処理で、一部が個別処理の場合

例例 ) ) ファイルのファイルの Open/CloseOpen/Close  トランザクションの  トランザクションの Begin/EndBegin/End  リトライ処理  リトライ処理     TreeTreeの走査の走査

Page 31: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

関数関数 a(x)a(x)

if(x == 1) 個別処理 1else 個別処理 2

共通処理

共通処理

●●値渡しによる処理の分岐値渡しによる処理の分岐

・個別処理が増える度に、・個別処理が増える度に、 関数の処理が増大する 関数の処理が増大する

・関数の引数に制御情報を渡している・関数の引数に制御情報を渡している =制御結合 =制御結合

Page 32: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

メソッドメソッド aa

Call メソッド b

共通処理

共通処理

●●個別処理の抽象化個別処理の抽象化(( template methodtemplate methodパターン)パターン)

・処理毎にクラスが増える・処理毎にクラスが増える

抽象メソッド b

抽象クラス A

Page 33: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

関数関数 a(f)a(f)

個別処理 f

共通処理

共通処理

●●関数渡しによる処理の再利用関数渡しによる処理の再利用

・個別処理が増えても・個別処理が増えても 関数本体が複雑にならない 関数本体が複雑にならない

・関数を値として扱える・関数を値として扱える =データ結合 =データ結合

Page 34: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

関数関数 a(f)(x)a(f)(x)

個別処理 f

共通処理

共通処理

個別処理 1個別処理 1

個別処理 2個別処理 2

個別処理 3個別処理 3

+

+

+

関数 a1(x)

関数 a2(x)

関数 a(x)

=

=

=

関数を組み合わせて新しい関数を関数を組み合わせて新しい関数を作るのも容易作るのも容易

Page 35: たのしい高階関数

ん?ん?

Page 36: たのしい高階関数

インターフェース渡しインターフェース渡しがあるじゃん!があるじゃん!

Page 37: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

例えば、例えば、あるリストの値をあるリストの値を 22倍した結果、倍した結果、1010以上のものを抜き出して全部足した値を求める以上のものを抜き出して全部足した値を求める場合。場合。

list.list.mapmap(_ * (_ * 22).).filterfilter(_ >= (_ >= 1010).).reducereduce(_ + _)(_ + _)

foldrfoldr (+) (+) 00 . . filterfilter (>= (>=1010) . ) . mapmap (* (*22) $ list) $ list

Page 38: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

list.list.mapmap((newnew Func1<Integer, Integer>Func1<Integer, Integer>() {() { publicpublic IntegerInteger applyapply((IntegerInteger a) { a) { returnreturn a * a * 22;};} }).}).filterfilter((newnew Func1<Integer, Boolean>Func1<Integer, Boolean>() {() { publicpublic BooleanBoolean applyapply((IntegerInteger a) { a) { returnreturn a >= a >= 1010;};}

}).}).reducereduce((newnew Func2<Integer, Integer, Integer>Func2<Integer, Integer, Integer>() {() { publicpublic IntegerInteger applyapply((IntegerInteger a, a, IntegerInteger b) { b) { returnreturn a + b; } a + b; } });});

Page 39: たのしい高階関数

やってられるか~!!やってられるか~!!

Page 40: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

処理の再利用の行いやすさ処理の再利用の行いやすさ

・高階関数は関数を引数に渡せるので、・高階関数は関数を引数に渡せるので、 処理の再利用が行いやすい 処理の再利用が行いやすい

・但し、型推論、ラムダ式など、手軽に関数を扱える・但し、型推論、ラムダ式など、手軽に関数を扱える 言語サポートが備わっていることが重要 言語サポートが備わっていることが重要

Page 41: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

処理の再利用の行いやすさ処理の再利用の行いやすさ

パターンとしての高階関数パターンとしての高階関数

Page 42: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

例えば、リストの全ての要素に関数を写す関数は例えば、リストの全ての要素に関数を写す関数は mapmap

List(List(11,,22,,33).).mapmap(_ * (_ * 22))

mapmap (* (*22) [) [11,,22,,33]]

[1,2,3].[1,2,3].mapmap((functionfunction(a) { (a) { returnreturn a * a * 22 }) })

JavaScript

Page 43: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

例えば、例えば、 ScalaScalaのの flatMapflatMapはモナドのはモナドの bindbindと分かればと分かれば以下の動作が容易に推測できる。以下の動作が容易に推測できる。

> List(1,2,3).flatMap(x => List(x*2))> List(1,2,3).flatMap(x => List(x*2))res0: List[Int] = List(2, 4, 6)res0: List[Int] = List(2, 4, 6)

> Some(1).flatMap(x => Some(x*2))> Some(1).flatMap(x => Some(x*2))res1: Option[Int] = Some(2)res1: Option[Int] = Some(2)

Page 44: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数を学ぶメリット高階関数を学ぶメリット

パターンとしての高階関数パターンとしての高階関数

・関数型言語にはパターンがある。・関数型言語にはパターンがある。

・パターンを覚えれば、他の関数型言語でも応用が利く。・パターンを覚えれば、他の関数型言語でも応用が利く。

Page 45: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?

高階関数を学ぶメリット

リストを扱う高階関数

まとめ

AgendaAgenda

Page 46: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

map関数map関数

filter関数filter関数

畳込み関数畳込み関数

・神は言われた。「リストあれ」・神は言われた。「リストあれ」

・リストと関数型言語は関連が深い・リストと関数型言語は関連が深い

・・ JavaJavaやってて「あれ欲しい」はやってて「あれ欲しい」は たいていリストの高階関数 たいていリストの高階関数

Page 47: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストのおさらいリストのおさらい

0 :: 1 :: 2 :: 3 :: Nil0 :: 1 :: 2 :: 3 :: Nil

1 2 3

[]

0

ヘッダヘッダ テイルテイル ラストラスト NilNil

0 : 1 : 2 : 3 : []0 : 1 : 2 : 3 : []

Page 48: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストのおさらいリストのおさらい

つまりですねつまりですね

Page 49: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストのおさらいリストのおさらい

こんなイメージこんなイメージ

ヘッダヘッダ テイルテイルラストラスト NilNil

Page 50: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

map関数map関数

filter関数filter関数

畳込み関数畳込み関数

Page 51: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

mapmap関数のイメージ関数のイメージ

[1,2,3,4[1,2,3,4・・・・ ,n] ,n]

関数関数 ffをリストに写す(をリストに写す( map overmap over))

[f(1), f(2), f(3), f(4)[f(1), f(2), f(3), f(4)・・・・ ,f(n)],f(n)]

map fmap f

Page 52: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

let let ベホマラー ベホマラー = map = map ベホイミベホイミ

こういう風に使いますこういう風に使います

let let ルカナン ルカナン = map = map ルカニルカニ

let let スクルト スクルト = map = map スカラスカラ

Page 53: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

mapmap関数の例関数の例

> map (\x -> x * 2) [1,2,3]> map (\x -> x * 2) [1,2,3][2,4,6][2,4,6]

> map (\x -> "hoge" ++ show(x)) [1,2,3]> map (\x -> "hoge" ++ show(x)) [1,2,3]["hoge1","hoge2","hoge3"]["hoge1","hoge2","hoge3"]

Page 54: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

mapmap関数の実装関数の実装

mapmap :: (a -> b) -> [a] -> [b] :: (a -> b) -> [a] -> [b]mapmap _ [] = [] _ [] = []mapmap f (x:xs) = f x : f (x:xs) = f x : mapmap f xs f xs

ヘッダヘッダ テイルテイル

Page 55: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

mapmap関数の実装関数の実装

defdef mapmap[[BB, , ThatThat](f: ](f: AA => => BB)) ((implicitimplicit bf: bf: CanBuildFromCanBuildFrom[[ReprRepr, , BB, , ThatThat])]) : : ThatThat = { = { valval b = b = bfbf(repr)(repr) b.b.sizeHintsizeHint(this)(this) forfor (x <- this) b += f(x) (x <- this) b += f(x) b.b.resultresult }}

Page 56: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

mapmap関数の実装(簡略化)関数の実装(簡略化)

def map[B, That](f: A => B)def map[B, That](f: A => B) (implicit bf: CanBuildFrom[Repr, B, That])(implicit bf: CanBuildFrom[Repr, B, That]) : That = {: That = { val b = bf(repr)val b = bf(repr) b.sizeHint(this)b.sizeHint(this) for (x <- this) b += f(x)for (x <- this) b += f(x) b.resultb.result }}

defdef mapmap[[AA, , BB](f: ](f: AA => => BB): ): ListList[[BB] = {] = { valval b = b = newnew ListBufferListBuffer[[BB]()]() b.b.sizeHintsizeHint(this)(this) forfor (x <- this) buff += f(x) (x <- this) buff += f(x) b.b.resultresult}}

Page 57: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

map関数map関数

filter関数filter関数

畳込み関数畳込み関数

Page 58: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

filterfilter関数のイメージ関数のイメージ

[1,2,3,4[1,2,3,4・・・・ ,n] ,n]

関数関数 ffで要素を篩いに掛けるで要素を篩いに掛ける

filter (x => x < 4) filter (x => x < 4)

[1,2,3] [1,2,3]

Page 59: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

こういう時に使います こういう時に使います ゲームしばり無視していますが。。ゲームしばり無視していますが。。

let let レベルレベル 55 デス デス = filter (not . is= filter (not . isレベルレベル 5)5)

Page 60: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

filterfilter関数の例関数の例

> filter (\x -> not(x `mod` 5 == 0)) [3,4,5,10,12]> filter (\x -> not(x `mod` 5 == 0)) [3,4,5,10,12][3,4,12][3,4,12]

Page 61: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

filterfilter関数の実装関数の実装

filterfilter :: (a -> Bool) -> [a] -> [a] :: (a -> Bool) -> [a] -> [a]filterfilter _pred [] = [] _pred [] = []filterfilter pred (x:xs) pred (x:xs) | pred x = x : | pred x = x : filterfilter pred xs pred xs | otherwise = | otherwise = filterfilter pred xs pred xs

Page 62: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

filterfilter関数の実装関数の実装

defdef filterfilter(p: (p: AA => => BooleanBoolean): ): ReprRepr = { = { valval b = b = newBuildernewBuilder forfor (x <- this) (x <- this) ifif (p(x)) b += x (p(x)) b += x b.b.resultresult}}

Page 63: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

map関数map関数

filter関数filter関数

畳込み関数畳込み関数

Page 64: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldl / foldrfoldl / foldr関数のイメージ関数のイメージ

foldr f 0 [1,2,3,4]foldr f 0 [1,2,3,4]

関数関数 ffでリストを畳み込んで単一の値を返す。でリストを畳み込んで単一の値を返す。左からと右からの畳み込み関数がある。左からと右からの畳み込み関数がある。

foldl f 0 [1,2,3,4] foldl f 0 [1,2,3,4]

ff11 ff

22 ff33 ff

44 00

ffff

ff

22ff00 11

3344

Page 65: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

一応やっときます一応やっときます

Page 66: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

右も左もないですが右も左もないですが

++ ++ ++ ++

==

Page 67: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldl / foldrfoldl / foldr関数の例関数の例

> let add x y = x + y> let add x y = x + y> foldl add 0 [1,2,3,4]> foldl add 0 [1,2,3,4]1010

> foldr add 0 [1,2,3,4]> foldr add 0 [1,2,3,4]1010

Page 68: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldl / foldrfoldl / foldr関数の例関数の例

> let add x y = x + y> let add x y = x + y> foldl add 0 [1,2,3,4]> foldl add 0 [1,2,3,4]= add(add(add(add(0, 1), 2), 3), 4)= add(add(add(add(0, 1), 2), 3), 4)= add(add(add(1, 2), 3), 4)= add(add(add(1, 2), 3), 4)= add(add(3, 3), 4)= add(add(3, 3), 4)= add(6, 4)= add(6, 4)=10=10

> foldr add 0 [1,2,3,4]> foldr add 0 [1,2,3,4]1010

Page 69: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldl / foldrfoldl / foldr関数の例関数の例

> let add x y = x + y> let add x y = x + y> foldl add 0 [1,2,3,4]> foldl add 0 [1,2,3,4]1010

> foldr add 0 [1,2,3,4]> foldr add 0 [1,2,3,4]= add(1, add(2, add(3, add(4, 0))))= add(1, add(2, add(3, add(4, 0))))= add(1, add(2, add(3, 4)))= add(1, add(2, add(3, 4)))= add(1, add(2, 7))= add(1, add(2, 7))= add(1, 9)= add(1, 9)= 10= 10

Page 70: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldrfoldr関数の実装関数の実装

foldrfoldr :: (a -> b -> b) -> b -> [a] -> b :: (a -> b -> b) -> b -> [a] -> bfoldrfoldr k z = go k z = go wherewhere go [] = zgo [] = z go (y:ys) = y `k` go ysgo (y:ys) = y `k` go ys

Page 71: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldrfoldr関数の実装関数の実装

foldrfoldr :: (a -> b -> b) -> b -> [a] -> b :: (a -> b -> b) -> b -> [a] -> bfoldrfoldr k z = go k z = go wherewhere go [] = zgo [] = z go (y:ys) = y `k` go ysgo (y:ys) = y `k` go ys

foldrfoldr k z [] = z k z [] = zfoldrfoldr k z (y:ys) = k y ( k z (y:ys) = k y (foldrfoldr k z ys) k z ys)

Page 72: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldlfoldl関数の実装関数の実装

foldlfoldl :: (a -> b -> a) -> a -> [b] -> a :: (a -> b -> a) -> a -> [b] -> afoldlfoldl f z0 xs0 = lgo z0 xs0 f z0 xs0 = lgo z0 xs0 wherewhere lgo z [] = zlgo z [] = z lgo z (x:xs) = lgo (f z x) xslgo z (x:xs) = lgo (f z x) xs

Page 73: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldlfoldl関数の実装関数の実装

foldlfoldl :: (a -> b -> a) -> a -> [b] -> a :: (a -> b -> a) -> a -> [b] -> afoldlfoldl f z0 xs0 = lgo z0 xs0 f z0 xs0 = lgo z0 xs0 wherewhere lgo z [] = zlgo z [] = z lgo z (x:xs) = lgo (f z x) xslgo z (x:xs) = lgo (f z x) xs

foldlfoldl f z [] = z f z [] = zfoldlfoldl f z (x:xs) = f z (x:xs) = foldlfoldl f (f z x) xs f (f z x) xs

Page 74: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldLeftfoldLeft関数の実装関数の実装 (Scala)(Scala)

defdef foldLeftfoldLeft[[BB](z: ](z: BB)(f: ()(f: (BB, , AA) => ) => BB): ): BB = { = { varvar acc = z acc = z varvar these = this these = this whilewhile (!these. (!these.isEmptyisEmpty) {) { acc = f(acc, these.acc = f(acc, these.headhead)) these = these.these = these.tailtail }} accacc}}

Page 75: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

foldRightfoldRight関数の実装関数の実装 (Scala)(Scala)

defdef foldRightfoldRight[[BB](z: ](z: BB)(f: ()(f: (AA, , BB) => ) => BB): ): BB = = ifif (this. (this.isEmptyisEmpty) z) z elseelse f(head, tail. f(head, tail.foldRightfoldRight(z)(f))(z)(f))

Page 76: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

ScalaScalaのの foldRightfoldRight関数の注意点関数の注意点

scala> (1 to 10000).toList.foldLeft(0)(_ + _)scala> (1 to 10000).toList.foldLeft(0)(_ + _)res0: Int = 50005000res0: Int = 50005000

scala> (1 to 10000).toList.foldRight(0)(_ + _)scala> (1 to 10000).toList.foldRight(0)(_ + _)java.lang.StackOverflowErrorjava.lang.StackOverflowError

Page 77: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

RangeRangeの場合は大丈夫の場合は大丈夫

scala> (1 to 10000).foldLeft(0)(_ + _)scala> (1 to 10000).foldLeft(0)(_ + _)res0: Int = 50005000res0: Int = 50005000

scala> (1 to 10000).foldRight(0)(_ + _)scala> (1 to 10000).foldRight(0)(_ + _)res1: Int = 50005000res1: Int = 50005000

Page 78: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

リストを扱う高階関数リストを扱う高階関数

RangeRangeのの foldRightfoldRight関数の実装関数の実装

defdef foldRightfoldRight[[BB](z: ](z: BB)(op: ()(op: (AA, , BB) => ) => BB): ): BB = = reversedreversed..foldLeftfoldLeft(z)((x, y) => op(y, x))(z)((x, y) => op(y, x))

まさかのまさかの reversedreversed!!

ReversedReversedはは ListList型を返すので、型を返すので、ListListのの foldLeftfoldLeftが使われるが使われる

Page 79: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

高階関数ってなに?

高階関数を学ぶメリット

リストを扱う高階関数

まとめ

AgendaAgenda

Page 80: たのしい高階関数

たのしい高階関数 たのしい高階関数 λλ  

・高階関数は関数を引数に渡せるので、処理の再利用が・高階関数は関数を引数に渡せるので、処理の再利用が 行いやすい(型推論やラムダ式などの言語支援が重要) 行いやすい(型推論やラムダ式などの言語支援が重要)

・パターンを覚えると、他の関数型言語でも応用が利く・パターンを覚えると、他の関数型言語でも応用が利く

・リスト処理の高階関数のように、便利で強力な関数が・リスト処理の高階関数のように、便利で強力な関数が 最初から用意されている 最初から用意されている

Page 81: たのしい高階関数

ご清聴ありがとうご清聴ありがとうございました!!ございました!!