Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
2019/6/27
1
プログラミング言語論(Concepts on Programming Languages)
趙 建軍情報知能工学部門
1
関数型プログラミング言語(Functional Programming Languages)
2019.06.272
第11回
2019/6/27
2
3
今日の講義
宣言型プログラミング
関数型プログラミング 歴史
関数型プログラム
プログラミングのパラダイム
4命令型
2019/6/27
3
プログラミングのパラダイム
5宣言型
宣言型プログラミングとは
宣言型プログラミング (Declarative programming)は、プログラミングパラダイムの名称だが、主として2種類の意味がある
第1の意味:処理方法ではなく対象の性質などを宣言することでプログラミングするパラダイムを意味する
第2の意味:純粋関数型プログラミング、論理型プログラミング、制約プログラミングの総称である
後者は前者の性質を持つ
6
2019/6/27
4
What vs How
7
命令型 vs 宣言型
8
2019/6/27
5
9
命令型 vs 宣言型
プログラミングのパラダイム
10宣言型
2019/6/27
6
プログラミングのパラダイム
11
関数型
12
関数型プログラミングとは (1)
Functional programming is style of programming in which the basic method of computation is the application of functions to arguments;
A functional language is one that supports and encourages the functional style.
Opinions differ, and it is difficult to give a precise definition, but generally speaking:
2019/6/27
7
関数型プログラミングとは (2)
様々な意見あり、詳細な定義は困難、けれども、一般には:
関数型プログラミングとは、計算の基本操作が引数に対する関数適用であり、プログラムは関数の合成であるとする プログラミングスタイル
関数型言語は、このプログラミングスタイルを支援し、ある意味で強制するプログラミング言語
13
関数型プログラミングとは (2)
関数型プログラミングとは複数の式を関数の適用によって組み合わせていくプログラミングスタイルである
Functional programming is a programming paradigm. A style of building the structure and elements of computer programs that treats computation as the evaluation of mathematical
functions and avoids changing-state and mutable data
14
2019/6/27
8
関数型 vs 命令型プログラム
命令型 Turing machine:計算機には「状態」があり、1
ステップずつ実行される命令によって、「状態」が変更されるもの
手順 (how) が決まっている。何をするか (what) は不鮮明
関数型 帰納的関数論:基本関数があって、それを合成
して複雑な関数を構成する 「状態」がない 何をすべきか (what) が決まっている。手順 (how)
は決まっていない 15
例 (1)
Summing the integers 1 to 10 in Java:
int total = 0;
for (int i = 1; i 10; i++)
total = total + i;
The computation method is variable assignment.
16
2019/6/27
9
例 (1)
Summing the integers 1 to 10 in Haskell:
sum [1..10]
The computation method is function application.
17
例 (2)
18
total = 0;for (i = 1; i <= 10; ++i)
total = total+i;
fun sum 0 = 0| sum n = n + sum (n-1);
変数への代入
関数の適用
2019/6/27
10
例 (3): 階乗関数
19
定義
0! = 1n! = n * (n-1)!
ML: 関数型
fun factorial 0 = 1| factorial n = n * factorial (n-1)
C: 通常
int factorial (int n) { int f;f = 1;while (n > 0) {
f = f * n;n = n – 1;
}return f;
}
C: 関数型的
int factorial (int n) { if (n == 0) return 1;else return n * factorial (n-1);
}
関数型 vs 命令型プログラム 表示的意味論によれば 命令型プログラムは関数型プログラムとして
記述することができる。なお、機械の状態を表すデータ構造を用いる
これは理論的結果である 私は“理論的” というのは“本当に正しい”
ということだと思うのだが(?)
実践にとってどんな意味があるか? 関数型言語を実応用に使うことができるか? コンパイラ, GUI, ネットワークのルータ, ….
20
2019/6/27
11
関数型プログラミングの特徴
21
純関数型プログラミング (pure functional programming)
first-class object としての関数
ラムダ式/ラムダ計算 (lambda calculus)
関数型プログラミングの特徴
純関数型プログラミング 式の値があれば、それはその部分式の値に
だけ依存する(つまり、副作用がない) 式は、評価されるたびに同じ値を持つ
22
参照の透明性 (tranceparency)
2019/6/27
12
純関数型プログラミングとは、変数や代入のないプログラミング
純関数型内部状態を持たない
命令型代入により内部状態が変化
23
関数型プログラミングの特徴
ほとんどの関数型言語は、代入操作を持つ
⇒ 純粋ではない
24
本質は、純粋な部分により支配されている
関数型プログラミングの特徴
2019/6/27
13
関数型プログラミングの特徴
関数の地位 -- first-class object としての関数
関数は、他のすべての値と同じ地位を持つ関数は、式の値となり得る関数を引数として渡すことができる関数を、データ構造の中に収めることも
出来る
25
関数型プログラミングの特徴
注: first-class object
第一級オブジェクト(一等値)プログラミング言語において、
計算対象となるデータ(値)のこと
26
2019/6/27
14
関数型プログラミングの特徴
ラムダ式/ラムダ計算 (lambda calculus)
関数を定義し、関数適用を繰返すことにより、計算を行う
ラムダ計算は、関数型プログラミングの理論的基盤である
27
1930s
Alonzo Church develops the lambda calculus, a simple but powerful theory of functions.
28
関数型プログラミングの歴史
2019/6/27
15
1950s
John McCarthy develops Lisp, the first functional language, with some influences from the lambda calculus, but retaining variable assignments.
29
関数型プログラミングの歴史
1960s
Peter Landin develops ISWIM, the first pure functional language, based strongly on the lambda calculus, with no assignments.
30
関数型プログラミングの歴史
2019/6/27
16
1970s
John Backus develops FP, a functional language that emphasizes higher-order functions and reasoning about programs.
31
関数型プログラミングの歴史
1970s
Robin Milner and others develop ML, the first modern functional language, which introduced type inference and polymorphic types.
32
関数型プログラミングの歴史
2019/6/27
17
1970s -1980s
David Turner develops a number of lazy functional languages, culminating in the Miranda system.
33
関数型プログラミングの歴史
1987
An international committee of researchers initiates the development of Haskell, a standard lazy functional language.
34
関数型プログラミングの歴史
2019/6/27
18
1990s
Phil Wadler and others develop type classes and monads, two of the main innovations of Haskell.
35
関数型プログラミングの歴史
36
2019/6/27
19
Abstract word cloud for Functional programming
37
BackusのTuring 賞
John Backus は言語設計者 Fortran, BNF, etc.
Turing 賞受賞(1977)
38
2019/6/27
20
BackusのTuring 賞
Turing 賞講演“Can Programming Be Liberated From the von Neumann Style?”,
(1977 Turing Award Lecture)
関数型言語は命令型言語に優る 関数型言語の方が、推論しやすい 並列性があり、より効率的 代数的法則 プログラムに関する推論 コンパイラの最適化
39
プログラムに関する推論
プログラムの正しさの証明 プログラムが依存していること全てを考慮す
る必要
関数型プログラムにおいては どんなデータ構造への依存もexplicit
従って 関数型プログラムに関する推論は易しい
40
2019/6/27
21
比較: C によるquicksort
41
Haskell によるQuicksort
非常に簡潔に書ける
これで全部 代入無し、ソート済みリストに関する式を書くのみ 配列インデックス無し、ポインタ無し、メモリ管理
なし、…42
2019/6/27
22
あるcase study
米国の海軍のあるセンターでのプログラム実験 別々のチームが別々の言語でプログラムする 結果にはかなりの違いがあった
不完全であったり実行できないものもあった 評価に携(たずさ)わった人の中には、プログラムを見たとき、
Haskellプログラムが完成していたことにかなり驚いた人がいた。というのもHaskellは抽象度の高い、仕様記述言語であると考えていたからである。 43
関数型 vs オブジェクト指向
44
2019/6/27
23
45
関数型 vs オブジェクト指向
ラムダ式 (lambda calculus)
関数をλ 式で表すsq(x) = x * x
sq = λx.* x x
46
関数値の計算方法=関数本体 (body)
引数がxであることを示す
2019/6/27
24
ラムダ式 (lambda calculus)
関数適用と関数抽象M、Nがλ式のとき MN を 関数適用 (application)という関数の呼出しに相当する
λx.M を 関数抽象 (abstraction) 、(またはラムダ抽象)という関数の定義に相当する
4747
ラムダ式 (lambda calculus)
λ式の定義 (M、Nはλ式とする) 変数はλ式である 関数適用 (MN) は λ式である 関数抽象 (λx.M) はλ式である
※ 紛(まぎ)らわしくない場合は、括弧は適宜省略できるものとする
48
2019/6/27
25
ラムダ計算 (lambda calculus)
λ計算とは関数の定義と実行を抽象化した計
算体系 λ式の「簡約」により、計算を行う λ算法ともいう
4949
ラムダ計算 (lambda calculus)
束縛変数 (bound variable)
式Mに出現する変数 xは、抽象化λx.Mにより束縛 (bind)されるという
(例) λx.+ x 1
x が仮引数として宣言されたことを
意味する
50
2019/6/27
26
ラムダ計算 (lambda calculus)
自由変数 (free variable) 束縛変数ではない変数
(例1) λx.+ x y
xは束縛変数であるが、yは自由変数である
51
ラムダ計算 (lambda calculus)
(例) g(x,y) = a * x * y では、
a が自由変数で x, yが束縛変数⇒ g = λx.λy. * * a x y
g(x) = a * x * y であるとすると、
yは aと同様の自由変数である⇒ g = λx. * * a x y
52
2019/6/27
27
ラムダ計算 (lambda calculus)
λ式の簡約(reduction) α変換 β簡約 η変換
53
ラムダ計算 (lambda calculus)
λ計算の用途 計算の意味論 計算可能性理論 型理論
λ式 / λ計算では、全ての「計算可能な関数」を表現し、計算することができる
54
2019/6/27
28
Scheme
以降は、LISPの方言である Schemeを題材とする Lispの中核部分を提供 比較的小規模
55Gerald Jay SussmanGuy L. Steele Jr.
Scheme
なぜ Lispなのか 最も早く開発された言語の一つ 1958 McCarthyにより設計された Fortranに次いで古い
再帰、first-class objectとしての関数、ガベッジコレクション、形式的言語定義などを最初に実現
統合プログラミング環境の先駆け
56
2019/6/27
29
Scheme
LISPの弱点 あまりに斬新な構文である "Lots of Irritating, Silly Parentheses“
LISPの実現が非効率であった(以前は)非常に計算が遅かった
57
Scheme
Schemeは、会話形式で動作する Schemeに対して、二種類の対話を考
える評価すべき式を与える名前を値で束縛する
Schemeは、評価した結果を表示する
58
2019/6/27
30
Scheme
例
59
> 3.14159
3.14159
> (define pi 3.14159)
pi
> pi
3.14159
プロンプト
結果表示
人が入力
名前を値で束縛
Scheme
式 括弧の中に、演算子とオペランドを前
置記法により記述する
EOP は、E1・・Ek に適用される演算子 E1・・Ek を評価してから、EOP を適用
する
60
(EOP E1 ・・・ Ek)
2019/6/27
31
Scheme
例
61
> (+ 2 3 5)
10
> (+ 4 (* 5 7))
39
> (acos -1)
3.141592653589793
Scheme
引用 式をデータとして扱う 引用された項目を評価したら、その
値はそれ自身となる 次の2通りの書き方がある
62
(quote <item>)'<item>
2019/6/27
32
Scheme
引用されていない名前は、ある値に束縛されている 下の pi は 変数名である
引用すると、綴りとして扱える
63
> pi3.14159
> (quote pi)pi
Scheme
例
64
> (define f *)f
> (f 2 3)6
> (define f '*)f
> (f 2 3)ERROR: Bad procedure *
乗算関数
綴り「*」を表す記号
2019/6/27
33
Scheme
関数定義 関数定義の構文
ラムダ式の構文は
65
(define <fname> <lambda-expr>)
関数名 ラムダ式
(lambda ( <param> ) <expr>)
仮引数 式 (本体)
Scheme
例
66
> (define square (lambda(x) (* x x)) )
square
> (square 5)
25
2019/6/27
34
Scheme
は、次の defineと同じ構造
λx.*xx というλ式(関数) と、 3.14159という実数が、同じ立場
67
(define square (lambda(x) (* x x)) )
(define pi 3.14159)
Scheme
条件式 条件式の形式 (1)
"if P then E1 else E2"Pが真ならばE1を評価し、偽ならばE2を評価する
68
(if P E1 E2 )
2019/6/27
35
Scheme
条件式の形式 (2)
"if P1 then E1 else if ・・・else if Pk then Ek else Ek+1"
69
(cond (P1 E1 )
・・・
(Pk Ek )
(else Ek+1 ) )
Scheme
条件式の利用例 = 再帰
70
nの階乗を求める関数?
2019/6/27
36
Scheme
条件式の利用例 = 再帰
71
(define fact(lambda (n)(if (<= n 1) 1
(* n (fact (- n 1))) )))
nの階乗を求める関数
Quiz Time!
2019/6/27 72
2019/6/27
37
練習問題
フィボナッチ数を求める関数 fibを、定義せよ
fib(0) = 0
fib(1) = 1
fib(n) = fib(n-1) + fib(n-2)
(ただし、n≧2)
73
解答
(define fib
(lambda (n)
(cond ((<= n 0) 0)
((= n 1) 1)
(else (+ (fib(- n 1))
(fib(- n 2))
)) )))
74
2019/6/27
38
解答 (別解)
(define fib
(lambda (n)
(if (<= n 0) 0
(if (= n 1) 1
(+ (fib(- n 1))
(fib(- n 2)) )) )))
75
まとめ
In functional programming:
The basic method of computation is the application of functions to arguments
A functional language is one that supports and encourages the functional style
76