(Translated by https://www.hiragana.jp/)
関数型プログラミング - Wikipedia コンテンツにスキップ

関数かんすうがたプログラミング

出典しゅってん: フリー百科ひゃっか事典じてん『ウィキペディア(Wikipedia)』
関数かんすうがた言語げんごから転送てんそう

関数かんすうがたプログラミング(かんすうがたプログラミング、えい: functional programming)とは、数学すうがくてき意味いみでの関数かんすうおも使つかうプログラミングのスタイルである[1]。 functional programming は、関数かんすうプログラミング(かんすうプログラミング)などとやくされることもある[2]

関数かんすうがたプログラミング言語げんごえい: functional programming language)とは、関数かんすうがたプログラミングを推奨すいしょうしているプログラミング言語げんごである[1]りゃくして関数かんすうがた言語げんごえい: functional language)ともいう[1]

概要がいよう

[編集へんしゅう]

関数かんすうがたプログラミングは、関数かんすう主軸しゅじくにしたプログラミングをおこなうスタイルである[1]。ここでの関数かんすうは、数学すうがくてきなものをし、引数ひきすうさだまれば結果けっかさだまるという参照さんしょう透過とうかせいつものである[1]

参照さんしょう透過とうかせいとは、数学すうがくてき関数かんすうおなじようにおなかえしきあたえたらかならおなかえすような性質せいしつである[1]つぎsquare 関数かんすうは、 2 となるようなしきあたえればかなら4かえし、 3 となるようなしきあたえればかなら9かえし、いかなる状況じょうきょうでもべつかえすということはなく、これが参照さんしょう透過とうかせい関数かんすういちれいとなる[1]

def square(n):
  return n ** 2

つぎcountup 関数かんすうは、おな1わたしても、それまでに countup 関数かんすうがどのような引数ひきすうばれていたかによって、がえ1, 2, 3, ... と変化へんかするため、引数ひきすうだけで結果けっかさだまらないような参照さんしょう透過とうかせいのない関数かんすうであり、数学すうがくてき関数かんすうとはいえない[1]

counter = 0
def countup(n):
  global counter
  counter += n
  return counter

関数かんすうがたプログラミングは、参照さんしょう透過とうかせいつような数学すうがくてき関数かんすう使つかっててたしき主役しゅやくとなる[1]べつ箇所かしょ定義ていぎされている処理しょり利用りようすることを、手続てつづがたプログラミング言語げんごでは「関数かんすう実行じっこうする」や「関数かんすうす」などと表現ひょうげんするが、関数かんすうがたプログラミング言語げんごでは「しき評価ひょうかする」という表現ひょうげん使つかわれる[3]

参照さんしょう透過とうかせい

[編集へんしゅう]

参照さんしょう透過とうかせいとは、おなあたえたらがえかならおなじになるような性質せいしつである[1]参照さんしょう透過とうかせいつことは、その関数かんすう状態じょうたいたないことを保証ほしょうする[4]状態じょうたいたない数学すうがくてき関数かんすうは、並列へいれつ処理しょり実現じつげんするのにてきしている[4]関数かんすうがたプログラミング言語げんごうちで、すべての関数かんすう参照さんしょう透過とうかせいつようなものを純粋じゅんすい関数かんすうがたプログラミング言語げんごという[4]

入出力にゅうしゅつりょく

[編集へんしゅう]

関数かんすうがたプログラミングでは、数学すうがくてき関数かんすうわせて計算けいさん表現ひょうげんするが、それだけではファイルのきのような外界がいかいとのやりりをようする処理しょり直接的ちょくせつてき表現ひょうげんできない[5]。このような外界がいかいとのやりりを I/O (入出力にゅうしゅつりょく)[5]数学すうがくてき計算けいさんをするだけ、つまり 1 + 1 のようなプログラムない完結かんけつする処理しょりならば、入出力にゅうしゅつりょく記述きじゅつできなくても問題もんだいないが、現実げんじつてきなプログラムにおいてはそうでない[5]

純粋じゅんすい関数かんすうがたプログラミング言語げんごにおいては、しき評価ひょうかすると同時どうじに I/O が発生はっせいする関数かんすう用意よういすることで入出力にゅうしゅつりょく実現じつげんする[5]。たとえば、 F# 言語げんごでは、printfn "Hi."評価ひょうかされると、 () というもどってくると同時どうじに、画面がめんHi.表示ひょうじされる I/O が発生はっせいする[5]

Haskell では、評価ひょうか同時どうじに I/O がおこなわれる関数かんすう存在そんざいしない[5]。たとえば、 putStrLn "Hi." というしき評価ひょうかされると IO () かたかえされるが画面がめんにはなに表示ひょうじされず、このが Haskell の処理しょりけいによって解釈かいしゃくされてはじめて画面がめんHi.表示ひょうじされる[5]I/O アクションとは、ファイルのきやディスプレイへの表示ひょうじなどのような I/O を表現ひょうげんするしきのことである[5][6]IO a というかたは、コンピュータへの指示しじあらわす I/O アクションを表現ひょうげんしている[5][7]。ここでの IOモナドばれるもののひとつである[8]

Clean では、一意いちいがたもちいて入出力にゅうしゅつりょくあらわす。

手法しゅほう

[編集へんしゅう]

最初さいしょかい集合しゅうごうとなる候補こうほ生成せいせいし、それらの要素ようそたいして1つ(もしくは複数ふくすう)のかいにたどりくまで関数かんすう適用てきようとフィルタリングをかえ手法しゅほうは、関数かんすうがたプログラミングでよくもちいられるパターンである[9]

Haskell では、関数かんすう合成ごうせいこう演算えんざん使つかってポイントフリースタイル関数かんすう定義ていぎすることができる[9]関数かんすうをポイントフリースタイルで定義ていぎすると、データより関数かんすうくようになり、どのようにデータがうつわっていくかではなく、どんな関数かんすう合成ごうせいしてなにになっているかということへ意識いしきくため、定義ていぎみやすく簡潔かんけつになることがある[9]関数かんすう複雑ふくざつになりすぎると、ポイントフリースタイルではぎゃく可読かどくせいわるくなることもある[9]

言語げんご

[編集へんしゅう]

関数かんすうがたプログラミング言語げんごとは、関数かんすうがたプログラミングを推奨すいしょうしているプログラミング言語げんごである[1]りゃくして関数かんすうがた言語げんごともいう[1]すべての関数かんすう参照さんしょう透過とうかせいつようなものを、とく純粋じゅんすい関数かんすうがたプログラミング言語げんご英語えいごばんという[4]。そうでないものを純粋じゅんすいであるという[5]

関数かんすうがたプログラミング言語げんごおおくは、言語げんご設計せっけいにおいてなんらかのかたちラムダ計算けいさんかかわっている[3]。ラムダ計算けいさんはコンピュータの計算けいさんをモデルする体系たいけいひとつであり、記号きごうれつ規則きそくもとづいて変換へんかんしていくことで計算けいさんおこなわれるものである[3]

関数かんすうがたプログラミング言語げんご
名前なまえ 型付かたつ 純粋じゅんすいせい 評価ひょうか戦略せんりゃく 理論りろんてき背景はいけい
Clean 静的せいてき型付かたつ 純粋じゅんすい 遅延ちえん評価ひょうか
Erlang 動的どうてき型付かたつ 純粋じゅんすい 正格せいかく評価ひょうか
F# 静的せいてき型付かたつ 純粋じゅんすい 正格せいかく評価ひょうか
Haskell[2] 静的せいてき型付かたつ[2] 純粋じゅんすい[2] 遅延ちえん評価ひょうか[2] 型付かたつきラムダ計算けいさん[3]
Idris 静的せいてき型付かたつ 純粋じゅんすい 正格せいかく評価ひょうか 型付かたつきラムダ計算けいさん
Lazy K かたなし 純粋じゅんすい 遅延ちえん評価ひょうか コンビネータ論理ろんり
LISP 1.5
Scheme
Common Lisp
Clojure
動的どうてき型付かたつ 純粋じゅんすい 正格せいかく評価ひょうか かたしラムダ計算けいさん[3]
LISP各種かくしゅ方言ほうげん[3] 方言ほうげんによる 方言ほうげんによる 方言ほうげんによる
Miranda 静的せいてき型付かたつ 純粋じゅんすい 遅延ちえん評価ひょうか
ML
Standard ML
OCaml
静的せいてき型付かたつ 純粋じゅんすい 正格せいかく評価ひょうか
Scala 静的せいてき型付かたつ 純粋じゅんすい 正格せいかく評価ひょうか
Unlambda かたなし 純粋じゅんすい 正格せいかく評価ひょうか コンビネータ論理ろんり
Lean 静的せいてき型付かたつ 純粋じゅんすい 正格せいかく評価ひょうか 型付かたつきラムダ計算けいさん

手続てつづがたプログラミングとの比較ひかく

[編集へんしゅう]

C 言語げんごJavaJavaScriptPythonRuby などの2017ねん現在げんざい使つかわれている言語げんごおおくは、手続てつづがた文法ぶんぽうっている[10]。そのような言語げんごでは、文法ぶんぽうとしてしき (expression) とぶん (statement) を[10]。ここでのしきは、計算けいさん実行じっこうして結果けっかるような処理しょり記述きじゅつするための文法ぶんぽう要素ようそであり、加減乗除かげんじょうじょ関数かんすうしなどから構成こうせいされている[10]。ここでのぶんは、なんらかの動作どうさおこなうようにコンピュータへ指示しじするための文法ぶんぽう要素ようそであり、条件じょうけん分岐ぶんきif ぶんやループの for ぶんwhile ぶんなどから構成こうせいされている[10]手続てつづがた文法ぶんぽうでは、しき必要ひつよう計算けいさんすすめ、その結果けっかもとにしてぶんでコンピュータ命令めいれいおこなうというかたちで、プログラムを記述きじゅつする[10]。このように、手続てつづがた言語げんご重要じゅうようなのはぶんである[10]

それにたいして、関数かんすうがた言語げんご重要じゅうようなのはしきである[10]関数かんすうがた言語げんごのプログラムはたくさんのしき構成こうせいされ、プログラムそのものもひとつのしきである[10]。たとえば、 Haskell では、プログラムの処理しょり記述きじゅつにおいてぶん使つかわれず、外部がいぶ定義ていぎむ import 宣言せんげん処理しょり一部いちぶとしてあつかえない[10]関数かんすうがた言語げんごにおけるプログラムの実行じっこうとは、プログラムをあらわしき計算けいさんすすめて、その結果けっかとして (value) をることである[10]しき計算けいさんすることを、評価ひょうかする (evaluate) という[10]

手続てつづがた言語げんごではコンピュータへの指示しじぶんとしてうえからじゅんならべてくのにたいして、関数かんすうがた言語げんごでは数多かずおお定義ていぎしたこまかいしきわせてプログラムをつく[10]手続てつづがた言語げんごではぶん重要じゅうようであり、関数かんすうがた言語げんごではしき重要じゅうようである[11]

しきぶんちがいとして、かたいているかどうかというのがある[11]しきかたつが、ぶんかたたない[11]。プログラムすべてがしきから構成こうせいされていて、つよ静的せいてき型付かたつけがされているのならば、プログラムの全体ぜんたい細部さいぶまで型付かたつけされることになる[11]。このように細部さいぶまで型付かたつけされているようなプログラムは堅固けんごなものになる[11]

歴史れきし

[編集へんしゅう]

1930年代ねんだい

[編集へんしゅう]

関数かんすうがた言語げんご開発かいはつにおいて、アロンゾ・チャーチが1932ねん[注釈ちゅうしゃく 1]と1941ねん[注釈ちゅうしゃく 2]発表はっぴょうしたラムダ計算けいさん研究けんきゅうほど基本きほんてき重要じゅうよう影響えいきょうあたえたものはない[12]。ラムダ計算けいさんは、それがかんがされた当時とうじプログラム実行じっこうするようなコンピュータ存在そんざいしなかったためにプログラミング言語げんごとしてなされなかったにもかかわらず、いまでは最初さいしょ関数かんすうがた言語げんごとされている[12]。1989ねん現在げんざい関数かんすうがた言語げんごは、そのほとんどがラムダ計算けいさん装飾そうしょくくわえたものとしてなせる[12]

1960年代ねんだい

[編集へんしゅう]

1960ねんジョン・マッカーシーひとし発表はっぴょうした LISP関数かんすうがた言語げんご歴史れきしにおいて重要じゅうようである[13]。ラムダ計算けいさんは LISP の基礎きそであるとわれるが、マッカーシー自身じしんが1978ねん[注釈ちゅうしゃく 3]説明せつめいしたところによると、匿名とくめい関数かんすう表現ひょうげんしたいというのが最初さいしょにあって、その手段しゅだんとしてマッカーシーはチャーチのラムダ計算けいさん選択せんたくしたにぎない[14]

歴史れきしてきえば、 LISPつづいて関数かんすうがたプログラミングパラダイムへ刺激しげきあたえたのは、1960年代ねんだいなかばのピーター・ランディン英語えいごばん成果せいかである[15]。ランディンの成果せいかハスケル・カリーアロンゾ・チャーチおおきな影響えいきょうけていた[15]。ランディンの初期しょき論文ろんぶんは、ラムダ計算けいさんと、機械きかいおよび高級こうきゅう言語げんご (ALGOL 60) との関係かんけいについて議論ぎろんしている[15]。ランディンは、1964ねん[注釈ちゅうしゃく 4]に、 SECD マシンばれる抽象ちゅうしょうてき機械きかい使つかって機械きかいてきしき評価ひょうかする方法ほうほうろんじ、1965ねん[注釈ちゅうしゃく 5]に、ラムダ計算けいさんで ALGOL 60 の自明じめいなサブセットを形式けいしきした[15]。1966ねん[注釈ちゅうしゃく 6]にランディンが発表はっぴょうした ISWIM(If You See What I Mean のりゃく)という言語げんごぐん)は、間違まちがいなく、これらの研究けんきゅう成果せいかであり、構文こうぶん意味いみろんにおいておおくの重要じゅうようなアイデアをふくんでいた[15]。 ISWIM は、ランディン本人ほんにんによれば、「 LISP を、その名前なまえにもあらわれたリストへのこだわり、手作業てさぎょうのメモリて、ハードウェアに依存いぞんした教育きょういく方法ほうほうおも括弧かっこ伝統でんとうへの妥協だきょう、から解放かいほうしようとするこころみとしてることができる」[15]関数かんすうがた言語げんご歴史れきしにおいて ISWIM はつぎのような貢献こうけんたした[16]

  • 構文こうぶんについての革新かくしん[15]
    • 演算えんざんまえおけ記法きほう記述きじゅつするのをやめて中置ちゅうち記法きほう導入どうにゅうした[15]
    • let ぶしと where ぶし導入どうにゅうして、さらに、関数かんすう順序じゅんじょなく同時どうじ定義ていぎでき、相互そうご再帰さいき可能かのうなようにした[15]
    • 宣言せんげんなどを記述きじゅつする構文こうぶんに、インデントにもとづいたオフサイドルールを使用しようした[15]
  • 意味いみろんについての革新かくしん[16]
    • 非常ひじょうちいさいが表現ひょうげんりょくがあるコア言語げんご使つかって、構文こうぶんてきゆたかな言語げんご定義ていぎするという戦略せんりゃく導入どうにゅうした[15]
    • 等式とうしき推論すいろん (equational reasoning) を重視じゅうしした[15]
    • 関数かんすうによるプログラムを実行じっこうするための単純たんじゅん抽象ちゅうしょう機械きかいとしての SECD マシンを導入どうにゅうした[16]

ランディンは「それをどうやっておこなうか」ではなく「それののぞましい結果けっかとはなにか」を表現ひょうげんすることに重点じゅうてんいており、そして、 ISWIM の宣言せんげんてきなプログラミング・スタイルは命令めいれいてきなプログラミング・スタイルよりもすぐれているというランディンの主張しゅちょうは、今日きょうまで関数かんすうがたプログラミングの賛同さんどうしゃたちから支持しじされてきた[17]。その一方いっぽうで、関数かんすうがた言語げんごへの関心かんしんたかまるまでは、さらに10ねんようした[17]。その理由りゆうひとつは、 ISWIM ライクな言語げんご実用じつようてき実装じっそうがなかったことであり、のところ、この状況じょうきょうは1980年代ねんだいになるまでわらなかった[17]

ケネス・アイバーソンが1962ねん[注釈ちゅうしゃく 7]発表はっぴょうした APL は、純粋じゅんすい関数かんすうがたプログラミング言語げんごではないが、その関数かんすうがたてき部分ぶぶんしたサブセットがラムダしきたよらずに関数かんすうがたプログラミングを実現じつげんする方法ほうほういちれいであるというてんで、関数かんすうがたプログラミング言語げんご歴史れきし考察こうさつするさい言及げんきゅうする価値かちはある[17]実際じっさいに、アイバーソンが APL を設計せっけいした動機どうきは、配列はいれつのための代数だいすうてきなプログラミング言語げんご開発かいはつしたいというものであり、アイバーソンのオリジナルばん基本きほんてき関数かんすうがたてき記法きほうもちいていた[17]。そのの APL では、いくつかの命令めいれいがたてき機能きのう追加ついかされている[17]

脚注きゃくちゅう

[編集へんしゅう]

注釈ちゅうしゃく

[編集へんしゅう]

出典しゅってん

[編集へんしゅう]

参考さんこう文献ぶんけん

[編集へんしゅう]
  • Church, Alonzo (1932ねん4がつ), “A Set of Postulates for the Foundation of Logic” (英語えいご), Annals of Mathematics 33 (2): 346, doi:10.2307/1968337, ISSN 0003-486X, JSTOR 1968337, https://jstor.org/stable/1968337 , Wikidata Q55890017
  • Church, Alonzo (1941ねん) (英語えいご), The Calculi of Lambda Conversion, プリンストン大学ぷりんすとんだいがく出版しゅっぱんきょく , Wikidata Q105884272
  • Hudak, Paul (1989ねん9がつ1にち), “Conception, evolution, and application of functional programming languages” (英語えいご), ACM Computing Surveys 21 (3): 359–411, doi:10.1145/72551.72554, ISSN 0360-0300 , Wikidata Q55871443
  • Iverson, Kenneth (1962ねん12月1にち) (英語えいご), A Programming Language, ジョン・ワイリー・アンド・サンズ, ISBN 978-0-471-43014-8, OL 26792153M , Wikidata Q105954505
  • McCarthy, John (1978ねん), History of LISP, doi:10.1145/800025.808387 , Wikidata Q56048080
  • Landin, Peter (1964ねん1がつ1にち), “The Mechanical Evaluation of Expressions” (英語えいご), The Computer Journal 6 (4): 308-320, doi:10.1093/COMJNL/6.4.308, ISSN 0010-4620 , Wikidata Q30040385
  • Landin, Peter (1965ねん), “Correspondence between ALGOL 60 and Church's Lambda-notation” (英語えいご), Communications of the ACM 8, ISSN 0001-0782 , Wikidata Q105941120
  • Landin, Peter (1966ねん3がつ1にち), “The next 700 programming languages” (英語えいご), Communications of the ACM 9 (3): 157-166, doi:10.1145/365230.365257, ISSN 0001-0782 , Wikidata Q54002422
  • Lipovača, Miran 田中たなか英行ひでゆき, 村主むらぬしたかしぎょうやく (2012ねん5がつ25にち), すごいHaskellたのしくまなぼう! (1st (1st printing) ed.), ム社むしゃ, ISBN 978-4-274-06885-0 , Wikidata Q105845956
  • 本間ほんま雅洋まさひろ; るい孝介こうすけ; 逢坂おうさかひびき『Haskell入門にゅうもん 関数かんすうがたプログラミング言語げんご基礎きそ実践じっせん』(1st (1st printing))技術評論社ぎじゅつひょうろんしゃ、2017ねん10がつ10日とおかISBN 978-4-7741-9237-6 , Wikidata Q105833610

外部がいぶリンク

[編集へんしゅう]

関連かんれん項目こうもく

[編集へんしゅう]