たのしい関数型
Upcoming SlideShare
Loading in...5
×
 

たのしい関数型

on

  • 5,020 views

第1回 関数型言語勉強会 大阪

第1回 関数型言語勉強会 大阪
の資料です。

Statistics

Views

Total Views
5,020
Views on SlideShare
3,371
Embed Views
1,649

Actions

Likes
1
Downloads
22
Comments
2

5 Embeds 1,649

http://sovmoess.tumblr.com 1621
http://www.tumblr.com 19
http://webcache.googleusercontent.com 6
http://assets.txmblr.com 2
https://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • p.64は間違えて入ってしまったページです。
    すいません m(__)m
    読み飛ばしてください。
    感想、ありがとうございます!
    Are you sure you want to
    Your message goes here
    Processing…
  • p.64は必要?p.65があればいらないような・・・
    なおp.57からp.60にかけてが初心者向けとしてわかりやすかったです。
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

たのしい関数型 たのしい関数型 Presentation Transcript

  • 怖くないよ怖くないよたのしい関数型 ー関数型言語入門
  • 目的本勉強会の趣旨 本セッションは関数型入門です たのしく関数型を学ぶことを目的 としております。
  • つまりですね
  • 目的本勉強会の趣旨 -ATENDより 本セッションは関数型入門です たのしく関数型を学ぶことを目的 としております。
  • 大事なことなので2回いいました
  • 注意事項
  • 注意事項 Monad 圏論 ストリクト解析 がどうとか α-変換、β-簡約 がどうとか関数型には難しい概念もありますが・・
  • 注意事項 Monad 圏論 ストリクト解析 がどうとか α-変換、β-簡約 がどうとか当セッションの範囲外です
  • 注意事項関数型には怖い人がいるらしいですが・・特に東方
  • 注意事項会場を間違えていませんか?
  • 注意事項THIS IS スパルタ!!
  • 注意事項ないです
  • たのしく学びましょう~
  • Status 所属 : SIer Java : 195 Scala : 30 小酒 信一 Hakell : 35 システムアーキテクト 協調性 : 2 せいべつ : おとこ レベル : 0x24 さいだいHP : 24 Twitter : s_kozake さいだいMP : 1 ステータス : 緊張 E GATEWAY ノートPC E 結婚指輪 GOLD : 0
  • 関数型とは?
  • 関数型とは?副作用を持たない関数を中心にしてプログラムを組み立てる手法
  • 関数型とは?副作用を持たない関数を中心にしてプログラムを組み立てる手法副作用を持たない関数とは?同じ関数をなんど呼び出しても。同じ引数についていつも同じ結果「今回」f(x) = a なら、「次回」もf(x)=a
  • 関数型とは?副作用を持たない関数を中心にしてプログラムを組み立てる手法副作用を持たない関数とは?同じ関数をなんど呼び出しても。同じ引数についていつも同じ結果「今回」f(x) = a なら、「次回」もf(x)=a = 等式推論
  • 具体例JavaでListを扱うコード List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); System.out.println(list.get(0)); // 1 list.set(0, 4); System.out.println(list.get(0)); // 4
  • 具体例JavaでListを扱うコード List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); System.out.println(list.get(0)); // 1 list.set(0, 4); 副作用 副作用 System.out.println(list.get(0)); // 4Listの内部状態を変更している
  • 具体例ScalaでListを扱うコード val list = List(1, 2, 3) println(list(0)) // 1 val list2 = list.updated(0, 4) println(list(0)) // 1 println(list2(0)) // 4
  • 具体例ScalaでListを扱うコード val list = List(1, 2, 3) println(list.apply(0)) // 1 val list2 = list.updated(0, 4) println(list.apply(0)) // 1 println(list2.apply(0)) // 4新しいListを作成している
  • 具体例JavaのStringクラス final String str = "abc"; System.out.println(str); // "abc" final String str2 = str.substring(1); System.out.println(str); // "abc" System.out.println(str2); // "bc"JavaのStringクラスは不変
  • なぜ関数型?
  • なぜ関数型?CPUのマルチコア化・10年後には、コア1000!?・今まで以上に平行プログラミングが重要・副作用のない関数型は並行処理と相性がいい
  • なぜ関数型?CPUのマルチコア化・10年後には、コア1000!?・今まで以上に平行プログラミングが重要・副作用のない関数型は並行処理と相性がいい Java8にラムダが導入されるのも、 CPUコア数増加に対応し、並行処理を 効率よく扱うため
  • なぜ関数型?高階関数・関数がファーストクラスオブジェクト・コードパターンを再利用しやすい・リストのライブラリが使いやすい ・map ・fiter ・foldl / foldr ・find ・etc..
  • なぜ関数型?内部DSL・Domain Specific Language、領域特化言語・高階関数や遅延評価をもつ関数型は 内部DSLを作成しやすい。 「ホスト言語」として有力候補
  • なぜ関数型?・「HOW」から「WHAT」へ ハードウェア性能の向上 関数型 オブジェクト オブジェクト 指向型 指向型 手続き型 手続き型 手続き型・クイックソートのコード例 qsort [] = [] qsort(x:xs) = qsort l ++ [x] ++ qsort r where l = [a | a <- xs, a < x] r = [a | a <- xs, a >= x]
  • なぜ関数型?ハッカーになれる!?LISP は、それをモノにしたときのすばらしい悟り体験のために勉強しましょう。この体験は、その後の人生でよりよいプログラマーとなる手助けとなるはずです。たとえ、実際には LISP そのものをあまり使わなくても。 ~ハッカーになろう~より抜粋 http://cruel.org/freeware/hacker.html
  • リストとは?
  • リストとは?・同じ型の要素の並び 関数型言語として最も代表的なデータ構造・神は言われた。「リストあれ」 リストを処理するのが関数型言語の プログラミングというほど、関連が深い・単一方向の線型リスト head tail head tail [] 1 2
  • リストとは?コード例(HaskellのREPLでの例)
  • リストとは?コード例(HaskellのREPLでの例) zs 0 ys xs [] 1 2 3
  • リストとは?文字列もリストとして扱われる
  • タプルとは?
  • タプルとは?・有限個の要素の組。 各要素の型は異なってもいい・要するに、構造体・要素数0のタプルはユニットと呼ばれる 要素数2のタプルは組、3は三つ組
  • タプルとは?人間関係で考えると 組 二股 三つ組
  • タプルとは?
  • リスト内包表記とは?
  • リスト内包表記とは?・数学の内包表記は、既存の集合から 新しい集合を生成する。 2 { X | X ∈ {1..5}} = {1, 4, 9, 16, 25}・既存のリストから新しいリストを生成する のがリスト内包表記
  • リスト内包表記とは? 2 [ X | X ← [1..5]] 生成器
  • リスト内包表記とは?複数の生成器も列挙できる。[ X×Y | X ← [1..3],Y←[1..3]] 生成器 生成器
  • リスト内包表記とは?Javaで書くと、こんなイメージ List<Integer> xs = new ArrayList<Integer>(); xs.add(1); xs.add(2); xs.add(3); List<Integer> ys = new ArrayList<Integer>(); ys.add(1); ys.add(2); ys.add(3); List<Integer> ret = new ArrayList<Integer>(); for (int x : xs) { for (int y : ys) { ret.add(x * y); } } System.out.println(ret);
  • リスト内包表記とは?ガードと呼ばれる論理式も使用できる[ X | X ← [1..10], X `mod` 2 =0] 生成器 ガード
  • リスト内包表記とは?複数の生成器とガードの組み合わせ[ X×Y | X ← [1..4], even X, Y←[1..4], oddY] 生成器 ガード 生成器 ガード [(0×1), (0×3),(2×1), (2×3),(4×1), (4×3)]
  • リスト内包表記とは?Javaで書くと、こんなイメージ for (int x : xs) { if (x % 2 == 0) { for (int y : ys) { if (y % 2 == 1) { ret.add(x * y); } } } } System.out.println(ret);
  • リスト内包表記とは?Scalaでは、for式をリスト内包表記として使える scala> for (x <- 0 to 4 if x % 2 == 0; y <- 0 to 4 if y % 2 == 1) yield x * y res3: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 0, 2, 6, 4, 12)
  • リスト内包表記とは?関数zip2つのリストをとり、対応する要素を組として1つのリストをつくる関数 zip [1,2,3] [4,5] 短いリストにあわせられる 短いリストにあわせられる
  • リスト内包表記とは?zipを人間関係で考えるとListWListM 余りは切り捨てられます 余りは切り捨てられます
  • 再帰関数とは?
  • 再帰関数とは?・関数自身を使って定義された関数のこと・関数型言語では、ループを実現する仕組み として再帰が使われる。・クイックソートのコード例qsort [] = []qsort(x:xs) = qsort l ++ [x] ++ qsort r where l = [a | a <- xs, a < x] r = [a | a <- xs, a >= x]
  • 再帰関数とは?Nまで階乗を求める関数 func 0 × 1 × 2 ×... N副作用を伴うループを使ったケースと副作用を伴わない再帰を使ったケースで書いてみる。
  • 再帰関数とは?副作用を伴うループを使ったケース def fact(n :Int):BigInt = { var ret = BigInt(1) for (i <- 1 to n) { ret = ret * i } ret }
  • 再帰関数とは?副作用を伴わない再帰を使ったケース def fact(n :Int):BigInt = { if (n == 0) { 1 } else { n * fact(n - 1) } }
  • 再帰関数とは?副作用を伴わない再帰を使ったケース def fact(n :Int):BigInt = { if (n == 0) { 1 } else { n * fact(n - 1) } }0の階乗は1 <=基底部nの階乗は n + (n-1)の階乗 <=再帰部
  • 再帰関数とは?再帰関数の考え方1. 型を定義する factはInt型のnを受け取り、BigInt型を返す def fact(n:Int):BigInt2. 場合分けをする3. 簡単な方を定義する4. 複雑な方を定義する
  • 再帰関数とは?再帰関数の考え方1. 型を定義する2. 場合分けをする nが0の場合 nが0以外の場合3. 簡単な方を定義する4. 複雑な方を定義する
  • 再帰関数とは?再帰関数の考え方1. 型を定義する2. 場合分けをする3. 簡単な方を定義する0の階乗は14. 複雑な方を定義する
  • 再帰関数とは?再帰関数の考え方1. 型を定義する2. 場合分けをする3. 簡単な方を定義する4. 複雑な方を定義するnの階乗は n × (n-1)の階乗
  • 再帰関数とは?再帰の問題点 > scala Fact1 10000 284625968091705451890641321211986889... > > scala Fact2 10000 java.lang.StackOverflowError :
  • 再帰関数とは?再帰の問題点 > scala Fact1 10000 284625968091705451890641321211986889... > > scala Fact2 10000 java.lang.StackOverflowError : fact(3) = 3 × fact(2) スタックの使いすぎ = 3 × 2 × fact(1) = 3 × 2 × 1 × fact(0) =3×2×1×0
  • 再帰関数とは?StackOverflowErrorが発生しないfact定義 def fact(n: Int):BigInt = { def factorial(n: Int, acc: BigInt):BigInt = { if (n == 0) { acc } else { factorial(n - 1, n * acc) } } factorial(n, 1) }
  • 再帰関数とは? def fact(n: Int):BigInt = { def factorial(n: Int, acc: BigInt):BigInt = { if (n == 0) { acc } else { factorial(n - 1, n * acc) } } factorial(n, 1) } fact(3) = factorial(3, 1) スタックを = factorial(3 - 1, 3 * 1) 消費しない = factorial(2 - 1, 2 * 3) = factorial(1 - 1, 3 * 6) = 24
  • 再帰関数とは? def fact(n: Int):BigInt = { def factorial(n: Int, acc: BigInt):BigInt = { if (n == 0) { acc } else { factorial(n - 1, n * acc) } } factorial(n, 1) } fact(3) = factorial(3, 1) スタックを = factorial(3 - 1, 3 * 1) 消費しない = factorial(2 - 1, 2 * 3) = factorial(1 - 1, 1 * 6) =6
  • 再帰関数とは?末尾再帰とは 一番最後に自分自身を再帰的 に呼び出している関数 末尾再帰関数の結果値を持ち運ぶ 引数accはアキュムレータと呼ばれる ちなみに、Java8よりJavaにも 末尾再帰が導入されるらしい
  • ラムダとは? だっちゃ
  • ラムダとは? 引数のパターン、および 引数から結果を計算する本体 からなる、関数名を含まない式。
  • ラムダとは? 引数のパターン、および 引数から結果を計算する本体 からなる、関数名を含まない式。 要は無名関数
  • ラムダとは? 引数のパターン、および 引数から結果を計算する本体 からなる、関数名を含まない式。 要は無名関数 こんな感じ=> λx.x+x引数のパターン 結果を計算する本体
  • ラムダとは? こんな感じに使える >(λx.x+x) 2 4
  • ラムダとは?例えば、add関数 add x y = x+yこのようにも表現できる add = λxy.x+y
  • ラムダとは?JavaScriptと比較すると分かりやすい。(厳密にはちがいますが。。)add = λxy.x+yvaradd = function(x,y){ return x+y; }
  • ラムダとは?Haskell > let f = n -> n * n > :type f f :: Integer -> Integer > f(10) 100Scala scala> val f = (n:Int) => n * n f: Int => Int = <function1> scala> f(10) res0: Int = 100
  • ラムダとは?Java8 public static interface Func<T, R> { public R eval(T p); } public static void main(String[] args) { Func<Integer, Integer> f = (Integer n) -> n * n; System.out.println(f.eval(10)); } > java Lambda 100
  • ラムダとは? SAM(Single Abstract Method) type SAM(Single Abstract Method) typeJava8 public static interface Func<T, R> { public R eval(T p); } public static void main(String[] args) { Func<Integer, Integer> f = (Integer n) -> n * n; System.out.println(f.eval(10)); } インターフェース実装の インターフェース実装の > java Lambda シンタックスシュガー シンタックスシュガー 100
  • 高階関数とは? 高 い 意  そ 識  れ で  が 書 高俺 く 階の 関 数 だ
  • 高階関数とは?引数として関数を取ったり、返り値として関数を返したりする関数高階関数を利用したライブラリ関数が超便利! ・map ・fiter ・foldl / foldr ・find ・etc..
  • 高階関数とは? 好きな関数:if そうだ!if式を作ろう ( ゚∀゚)o彡°
  • 高階関数とは?Haskell myIf :: Bool -> a -> a -> a myIf cond t f = case cond of True -> t False -> f実行結果 > let a = myIf (1==1) (n -> n+n) (n -> n*n) > :type a a :: Integer -> Integer > a 10 20
  • 高階関数とは?Scala def myIf[T] (cond: Boolean, t: => T, f: => T):T = cond match { case true => t case false => f } val a = myIf(1 == 1, (n:Int) => n + n, (n:Int) => n * n) println(a(10))実行結果 > scala MyIf 20
  • 高階関数とは?Java8public static <T, R> Func<T, R> myIf(boolean cond, Func<T, R> t, Func<T, R> f) { return cond ? t : f;}public static void main(String[] args) { Func<Integer, Integer> a = myIf(1==1,(Integer n) -> n + n, (Integer n) -> n * n); System.out.println(a.eval(10));}実行結果> java MyIf20
  • クロージャーとは?
  • クロージャーとは?Scala 実行結果object Closure extends App { >scala Closure def inc(n:Int): () => Int = { 2 var m = n 3 () => { m = m + 1; m } 11 } 12 val f1 = inc(1) val f2 = inc(10) println( f1() ); println( f1() ); println( f2() ); println( f2() );}
  • クロージャーとは?クロージャーとは関数の一種引数以外の変数を、自身が定義された環境において解決する仕組み関数とメモリ空間のセット関数にメモリ空間がくっついているイメージ
  • カリー化とは? カリー  カリー
  • カリー化とは?カレーじゃないよ。論理学者 Haskell Curry さんの名前からつけられた。関数は関数を返り値として返せる性質を活かし、二つ以上の引数を持つ関数を、一度に一つの引数を取る関数として定義することをカリー化と表現する。
  • カリー化とは?x と y の和を求めるadd関数 a -> (a ->a) add は1つの数値をとり、 数値をとって数値を返す関数 を返す
  • カリー化とは?x と y の和を求めるadd関数 部分適用 という
  • カリー化とは?Scala scala> def add(x:Int)(y:Int) = x + y add: (x: Int)(y: Int)Int scala> val addOne = add(1)_ addOne: Int => Int = <function1> scala> addOne(10) res0: Int = 11
  • How to Study?
  • How to Study?おすすめ本(Haskell) プログラミングHaskell ふつうのHaskellプログラミング
  • How to Study?おすすめ本(Scala) Scala 第2版(コップ本) Scala実践プログラミングの3章
  • ご清聴ありがとうございました!