79
2010.4.17 F#λNobuhisa Koizumi

F#入門 ~関数プログラミングとは何か~

Embed Size (px)

DESCRIPTION

CLR/Hの第47回勉強会の3つめのセッション、『F#入門』の資料です

Citation preview

Page 1: F#入門 ~関数プログラミングとは何か~

2010.4.17 F#λ門Nobuhisa Koizumi

Page 2: F#入門 ~関数プログラミングとは何か~

• 自己紹介

• CLR/H の紹介

Page 3: F#入門 ~関数プログラミングとは何か~

自己紹介

• K泉将久

• id:Nobuhisa, @nobuhisa_k

• 1987年生まれの永遠の17歳

• 高2の時に独学でプログラミング

• 高3夏 セキュリティキャンプ2005

• 2006年2月 VS2005ローンチで初CLR/H

• 心理学, 生命科学, 認知神経科学

Page 4: F#入門 ~関数プログラミングとは何か~

自己紹介• C, HSP

• C++, C#

• Scheme

• VB, Common Lisp, Java,Python, PHP, JavaScript

• Haskell, Smalltalk

• OCaml, F#

Page 5: F#入門 ~関数プログラミングとは何か~

F# ... ?

Page 6: F#入門 ~関数プログラミングとは何か~

古くて新しい言語F#

F#

OCaml

ML

Haskell

MirandaCaml

Page 7: F#入門 ~関数プログラミングとは何か~

古くて新しい言語F#

F#

OCaml

ML

Haskell

MirandaCaml

1996- 2005(02)-

1987-921980-81

1985-86

1987(90)-

Page 8: F#入門 ~関数プログラミングとは何か~

C#(VB)の主要機能

Page 9: F#入門 ~関数プログラミングとは何か~

C#(VB)の主要機能

• Garbage Collection

• デリゲート

–匿名メソッド (2.0)

– λ式 (3.0)

• ジェネリクス (2.0)

• 型推論 (3.0)

• 対話環境 (X.0 ?)

など

Page 10: F#入門 ~関数プログラミングとは何か~

C#(VB)の主要機能

• Garbage Collection

• デリゲート

–匿名メソッド (2.0)

– λ式 (3.0)

• ジェネリクス (2.0)

• 型推論 (3.0)

• 対話環境 (X.0 ?)

など

1980年生まれのMLはこれらを全て備えていた !

Page 11: F#入門 ~関数プログラミングとは何か~

F#の魅力! -マルチパラダイム

言語指向プログラミング

手続き型プログラミング

関数プログラミング

オブジェクト指向

メタプログラミング

Page 12: F#入門 ~関数プログラミングとは何か~

F#の魅力! -美しい & 賢い

• Haskell, Python から得た見た目の美しさ

– OCaml はソースが見にくいと言われていた

– lightweight syntax

• 強く美しいパターンマッチ

• リスト内包表記 (Sequence Expressions)

> [ for x in 1..10 -> x * 2 ] ;;

• コンパイラの最適化が高度 & 処理が速い!

Page 13: F#入門 ~関数プログラミングとは何か~

F#かわいい

• 計算機科学の英知を脈々と受け継ぎ、

• Active Pattern, Computation Expressionsなどの新しい試みも加わり、

• .NET の最新テクノロジを利用でき、

– WinForm, WPF はもちろん、並列計算も

• ソースコードがきれいで、

• 優れた開発環境で開発できる!

Page 14: F#入門 ~関数プログラミングとは何か~

F#のダメなとこ!• Express Edition がない

• 開発環境の機能が不完全

– フォームデザイナ

– インテリセンス、クラスビュー、 etc ...

• 日本語情報の不足

–書籍は現在1冊

– OCaml の本を読んでもいいかも

時が解消してくれるかな・・・?

Page 15: F#入門 ~関数プログラミングとは何か~

Install

Page 16: F#入門 ~関数プログラミングとは何か~

Visual Studio 2010 !

• Visual F# 2010 Express の提供ナシ(´・ω・`)

• VS2010 Professional 以上を使おう

• VS Shellを使おう

• VS2008 + F# CTPを使おう

• テキストエディタ + fsc を使おう

Page 17: F#入門 ~関数プログラミングとは何か~

Visual Studio 2010 !

Visual Studio Shell• IronPython, F#, etc ...

• 2010用の提供はまだ(10/04/17時点)

F# CTP (Ver 2.0.0.0)• VS2008 or VS2008 Shell

• Download details: F# April 2010 CTP

Page 18: F#入門 ~関数プログラミングとは何か~
Page 19: F#入門 ~関数プログラミングとは何か~

FunctionalProgramming

Page 20: F#入門 ~関数プログラミングとは何か~

関数プログラミング

• 機能(関数)の集まりとして表現する

• 関数は第一級の扱いを受ける

• 再帰は別に本質ではない

• 副作用がない(少ない)

–副作用 :状態を変化させて結果に影響を与える

Page 21: F#入門 ~関数プログラミングとは何か~

変数

Page 22: F#入門 ~関数プログラミングとは何か~

変数宣言

• 値は変更できない

• 値に変数(名前、ラベル、シンボル)を束縛する

let itbe = ”THE BEATLES” ;;

値変数B

変数A

変数

Page 23: F#入門 ~関数プログラミングとは何か~

なぜ値は変更できない?

• 状態に依存しなくなる

• いかなる状況下でも、いつも同じ結果

–同じ引数で呼び出せば、同じ結果が返ってくる

• 再利用性が高くなる

• 関数のテストが簡単に!

• アルゴリズムが明確になる

• 並列計算

参照透明性

Page 24: F#入門 ~関数プログラミングとは何か~

タプル

Page 25: F#入門 ~関数プログラミングとは何か~

複数の値をひとつの値に!

• タプル (e1, e2, …, en)

> (1, 2) ;;val it : int * int = (1, 2)

> ("one", 2, 3.0) ;;val it : string * int * float = ("one", 2, 3.0)

> let a = () ;;val a : unit = ()

Page 26: F#入門 ~関数プログラミングとは何か~

関数

Page 27: F#入門 ~関数プログラミングとは何か~

純粋な関数ラムダ計算においては、関数は常に一引数

関数定義: 関数適用:

fun x -> x + 1 ;; f x ;;

> let myFun = fun x -> x * x ;;val myFun : int -> int

> myFun 10 ;;val it : int = 100

Page 28: F#入門 ~関数プログラミングとは何か~

純粋な関数ラムダ計算においては、関数は常に一引数

関数定義: 関数適用:

fun x -> x + 1 ;; f x ;;

> let myFun = fun x -> x * x ;;val myFun : int -> int

> myFun 10 ;;val it : int = 100

複数の引数を扱うにはどうすればいいの?

Page 29: F#入門 ~関数プログラミングとは何か~

タプルを使おう!

let stream = // .NET Framework のメソッドFile.Open ("a.txt", FileMode.Open, FileAccess.Read)

> let myFun = fun (x, y) -> x + y ;;val myFun : int * int -> int

> myFun (30, 70) ;;val it : int = 100

Page 30: F#入門 ~関数プログラミングとは何か~

練習(fst, snd)

タプルの第1要素を返す関数を定義してみよう

Keyword : ワイルドカード、総称型、型推論

> let fst' = fun (x, _) -> x ;;val fst' : 'a * 'b -> 'a

> fst' ("first", 2) ;;val it : string = "first"

Page 31: F#入門 ~関数プログラミングとは何か~

練習(fst, snd)

みなさんわかりましたか??

Page 32: F#入門 ~関数プログラミングとは何か~

練習(fst, snd)

では、第2要素を返す

snd’関数を定義してください

Page 33: F#入門 ~関数プログラミングとは何か~

ここからがFunctional

Page 34: F#入門 ~関数プログラミングとは何か~

関数の中に関数?

λx.λy. x y

> let f = (fun x -> (fun y -> x + y)) ;;val f : int -> int -> int

> f 10 ;;val it : (int -> int) = <fun:it@38-6>

Page 35: F#入門 ~関数プログラミングとは何か~

関数の中に関数?

> (f 4) 6 ;;val it : int = 10

> f 1 2 ;; // 左結合val it : int = 3

関数を入れ子にすることで、複数の引数を扱う関数を表現できる!

Page 36: F#入門 ~関数プログラミングとは何か~

関数の中に関数?

let add = fun x -> fun y -> fun z -> x+y+z ;;

> add 20 30 50 ;;

⇒ (fun x -> (fun y -> (fun z -> x + y + z))) 20 30 50

⇒ (fun y -> (fun z -> 20 + y + z)) 30 50

⇒ (fun z -> 20 + 30 + z) 50

⇒ 20 + 30 + 50

⇒ 100 !!

Page 37: F#入門 ~関数プログラミングとは何か~

省略記法

let f = fun x -> fun y -> fun z -> x y z ;;

let f = fun x y z -> x y z ;;

let f x y z = x y z ;;

Page 38: F#入門 ~関数プログラミングとは何か~

カリー化と部分適用

Page 39: F#入門 ~関数プログラミングとは何か~

カリー化とは?

• f (x, y, z)

「x を受け取り、[残りの引数をとる関数]を返す」形に変形する

let f (x, y, z) = x + y + z ;;

let f x = (fun (y, z) -> x + y + z) ;;

let f x = (fun y -> (fun z -> x + y + z)) ;;

Page 40: F#入門 ~関数プログラミングとは何か~

カリー化とは?

> let f1 (x, y, z) = x + y + z ;;val f1 : int * int * int -> int

> let f2 x y z = x + y + z ;;val f2 : int -> int -> int -> int

> f1 10 ;; // Error> f2 10 ;;val it : (int -> int -> int) = <fun:it@66-7>

Page 41: F#入門 ~関数プログラミングとは何か~

カリー化とは?

• ‘a * ‘b -> ‘c を

• ‘a -> ‘b -> ‘c に変換するのがカリー化

• let f x y z = ~ で定義されるのはカリー化された関数

Page 42: F#入門 ~関数プログラミングとは何か~

部分適用とは?

> let f x y = x + y ;; // fun x -> fun y -> x + yval f : int -> int -> int

> let add1 = f 1 ;; // fun y -> 1 + y ;;val add1 : (int -> int)

> add1 9 ;;val it : int = 10

> add1 99 ;;val it : int = 100

Page 43: F#入門 ~関数プログラミングとは何か~

練習(curry, uncurry)

‘a * ‘b -> ‘c の型の関数をカリー化する関数を定義しよう

> let curry f x y = f (x, y) ;; // 高階関数val curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c

> let f1 (x, y) = x + y ;;val f1 : int * int -> int

> let f2 = curry f1 ;; //部分適用val f2 : (int -> int -> int)

> f2 50 80 ;;val it : int = 130

Page 44: F#入門 ~関数プログラミングとは何か~

練習(curry, uncurry)

みなさんわかりましたか??

Page 45: F#入門 ~関数プログラミングとは何か~

練習(curry, uncurry)

では、

‘a -> ‘b -> ‘c の型の関数を

‘a * ‘b -> ‘c の型に変換する

uncurry関数を定義してください

Page 46: F#入門 ~関数プログラミングとは何か~

List

Page 47: F#入門 ~関数プログラミングとは何か~

リスト• 単方向連結リスト

• List の定義

– []

– x :: List

> [] ;; => val it : 'a list = []

> 1 :: [] ;; => val it : int list = [1]

> 1 :: 2 :: 3 :: [] ;;

val it : int list = [1; 2; 3]

Page 48: F#入門 ~関数プログラミングとは何か~

リストList の定義

– []

– x :: List

> List.head [1; 2; 3] ;;

val it : int = 1

> List.tail [1; 2; 3] ;;

val it : int list = [2; 3]

> List.head (List.tail (List.tail [1; 2; 3])) ;;???

Page 49: F#入門 ~関数プログラミングとは何か~

リストList の定義

– []

– x :: List

> List.head [1; 2; 3] ;;

val it : int = 1

> List.tail [1; 2; 3] ;;

val it : int list = [2; 3]

> List.head (List.tail (List.tail [1; 2; 3])) ;;val it : int = 3

Page 50: F#入門 ~関数プログラミングとは何か~

Listモジュールappend

average

averageBy

choose

collect

concat

empty

exists

exists2

filter

find

findIndex

fold

fold2

foldBack

foldBack2

forall

forall2

head

init

isEmpty

iter

iter2

iteri

iteri2

length

map

map2

map3

mapi

mapi2

max

maxBy

min

minBy

nth

ofArray

ofSeq

partition

permute

pick

reduce

reduceBack

replicate

rev

scan

scanBack

sort

sortBy

sortWith

sum

sumBy

tail

toArray

toSeq

tryFind

tryFindIndex

tryPick

unzip unzip3

zip zip3

Page 51: F#入門 ~関数プログラミングとは何か~

List.map : ('a -> 'b) -> 'a list -> 'b listすべての要素に関数を適用

> let add1 x = x + 1 ;;val add1 : int -> int

> List.map add1 [9; 99; 999] ;;val it : int list = [10; 100; 1000]

> List.map (fun x -> x + 1) [1; 2; 3] ;;val it : int list = [2; 3; 4]

Page 52: F#入門 ~関数プログラミングとは何か~

List.map : ('a -> 'b) -> 'a list -> 'b listすべての要素に関数を適用

> ( + ) ;;val it : (int -> int -> int) = <fun:it@25-4>

> ( + ) 1 1 ;;val it : int = 2

> List.map (( + ) 1) [1; 2; 3] ;; // 部分適用val it : int list = [2; 3; 4]

Page 53: F#入門 ~関数プログラミングとは何か~

List.filter : ('a -> bool) -> 'a list -> 'a list

関数の適用結果が真の要素だけ抽出

> let even x = x % 2 = 0 ;;val even : int -> bool

> List.filter even [1; 2; 3; 4; 5; 6; 7; 8] ;;val it : int list = [2; 4; 6; 8]

> List.filter (( < ) 4) [1; 5; 6; 2; 3; 7] ;;val it : int list = [5; 6; 7]

Page 54: F#入門 ~関数プログラミングとは何か~

定義してみると・・・

let rec MyMap f list' =match list' with| [] -> []| x :: rest -> f x :: MyMap f rest

let rec MyFilter f = function| [] -> []| x :: rest when f x -> x :: MyFilter f rest| _ :: rest -> MyFilter f rest

これは何だ・・・(?_?)

Page 55: F#入門 ~関数プログラミングとは何か~

パターンマッチ

Page 56: F#入門 ~関数プログラミングとは何か~

パターソマッチ

let MyMatch1 tuple =match tuple with| (0, 0) -> "zero"| (x, y) when x > y -> ">"| (x, y) when x < y -> "<"| _ -> "="

> MyMatch1 (3, 5) ;;val it : string = "<"

> MyMatch1 (2, 2) ;;val it : string = "="

Page 57: F#入門 ~関数プログラミングとは何か~

もしパターンマッチがなかったら...

let MyMatch1' tuple =if fst tuple = 0

&& snd tuple = 0 then "zero"elif fst tuple > snd tuple then ">"elif fst tuple < snd tuple then "<"else "="

Page 58: F#入門 ~関数プログラミングとは何か~

パターンマッ千

let MyMatch2 list' =match list' with| [] -> 0| [x] -> x| [x; y] -> x - y| _ -> failwith "エラー!"

> MyMatch2 [13; 3] ;;val it : int = 10

> MyMatch2 [1; 2; 3] ;;System.Exception: エラー!

Page 59: F#入門 ~関数プログラミングとは何か~

八゚ターンマッチ

let rec MyMatch3 list' =match list' with| [] -> 0| x :: rest -> x + MyMatch3 rest

> [1 .. 5] ;;val it : int list = [1; 2; 3; 4; 5]

> MyMatch3 [1 .. 3] ;;???

Page 60: F#入門 ~関数プログラミングとは何か~

八゚ターンマッチ

let rec MyMatch3 list' =match list' with| [] -> 0| x :: rest -> x + MyMatch3 rest

> [1 .. 5] ;;val it : int list = [1; 2; 3; 4; 5]

> MyMatch3 [1 .. 3] ;;val it : int = 6

Page 61: F#入門 ~関数プログラミングとは何か~

パ夕ーンマッチ

type Color =| Red| Green| Blue| White

let MyMatch4 color =match color with| Red -> "あか"| Green -> "みどり"| _ -> "そのた"

Page 62: F#入門 ~関数プログラミングとは何か~

pat :=

const -- constant pattern

long-ident pat-paramopt patopt -- named pattern

_ -- wildcard pattern

pat as ident -- "as" pattern

pat '|' pat -- "or" pattern

pat '&' pat -- "and" pattern

pat :: pat -- "cons" pattern

pat : type -- pattern with type constraint

pat,...,pat -- tuple pattern

(pat) -- parenthesized pattern

list-pat -- list pattern

array-pat -- array pattern

record-pat -- record pattern

:? atomic-type -- dynamic type test pattern

:? atomic-type as ident -- dynamic type test pattern

null -- null-test pattern

attributes pat -- pattern with attributes

Page 63: F#入門 ~関数プログラミングとは何か~

ここからは概要のみ

Page 64: F#入門 ~関数プログラミングとは何か~

オブジェクト指向

Page 65: F#入門 ~関数プログラミングとは何か~

[<AbstractClass>]type BaseClass() =

abstract Method1 : int -> int

type IBase =abstract Method2 : int -> int

type SubClass() =inherit BaseClass()override self.Method1 x = x + 10interface IBase with

member self.Method2 x = x * 10

Page 66: F#入門 ~関数プログラミングとは何か~

Units Of Measure

Page 67: F#入門 ~関数プログラミングとは何か~

[<Measure>] type h[<Measure>] type km[<Measure>] type cm[<Measure>] type cm2 = cm ^ 2

> 155<km/h> ;;val it : int<km/h> = 155

> 5<cm> * 8<cm> ;;val it : int<cm ^ 2> = 40

> let a : int<cm2> = 2<cm> * 10<cm> ;;val a : int<cm2> = 20

> 1<h> + 2<cm> ;;error: The unit of measure 'cm' does not match the unit of measure 'h'

Page 68: F#入門 ~関数プログラミングとは何か~

Active Pattern

Page 69: F#入門 ~関数プログラミングとは何か~

let (|S|A|B|C|) score =if score >= 80 then Selif score >= 60 then Aelif score >= 40 then Belse C

let GiveGrade score =match score with| S -> "たいへんよい"| A -> "よい"| B -> "がんばろう"| C -> "ゆとり"

Page 70: F#入門 ~関数プログラミングとは何か~

Quotation

Page 71: F#入門 ~関数プログラミングとは何か~

> <@ let f x = x + 10 in f 90 @> ;;val it : Expr<int> =

Let (f,

Lambda (x,

Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),

[x, Value (10)])), Application (f, Value (90)))

{CustomAttributes = [NewTuple (Value ("DebugRange"),

NewTuple (Value ("stdin"), Value (5), Value (7), Value (5), Value (10)))];

Raw = ...;

Type = System.Int32;}

式を <@ ~ @>で囲うと、式木を得られる

Microsoft.FSharp.Quotations

Page 72: F#入門 ~関数プログラミングとは何か~

let MyFun = function| Var v -> "変数だよー : " + v.Name| Value (o, _) -> "定数値だよー : " + o.ToString ()| NewTuple _ -> "タプルだよー"| Call _ -> "関数呼び出しだよー"| Lambda _ -> "λ式だよー"| _ -> "その他"

> MyFun <@ 100 @> ;;val it : string = "定数値だよー : 100"

> MyFun <@ 1 + 1 @> ;;val it : string = "関数呼び出しだよー"

> MyFun <@ fun x -> x @> ;;val it : string = "λ式だよー"

Microsoft.FSharp.Quotations.Patterns

Page 73: F#入門 ~関数プログラミングとは何か~

並列処理- Demo -

Page 74: F#入門 ~関数プログラミングとは何か~

PLINQ(PSeq)- Demo -

Page 75: F#入門 ~関数プログラミングとは何か~

アクター- Demo -

Page 76: F#入門 ~関数プログラミングとは何か~

FSUG-JP

Page 77: F#入門 ~関数プログラミングとは何か~

F# User Group - Japan

• http://groups.google.co.jp/group/fsug-jp( http://bit.ly/fsug-jp )

• 国内最大級のF#オンラインコミュニティ!!

• お気軽にご参加ください

• Twitter : #fsugjp

Page 78: F#入門 ~関数プログラミングとは何か~

(時間があまれば)質問タイム

Page 79: F#入門 ~関数プログラミングとは何か~

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