1 :デフォルトの名無しさん:2009/09/09(水) 13:31:46
Lisp Scheme ML Haskell FP Mirranda など
関数型言語について話し合いましょう。

前スレ
関数型言語Part IV
http://pc12.2ch.net/test/read.cgi/tech/1083649982/

関連スレ

Lisp Scheme Part27
http://pc12.2ch.net/test/read.cgi/tech/1248657331/

関数型言語ML (SML, OCaml, etc.), Part 6
http://pc12.2ch.net/test/read.cgi/tech/1245017721/

関数型プログラミング言語Haskell Part11
http://pc12.2ch.net/test/read.cgi/tech/1252382593/

Emacs Lisp 3
http://pc12.2ch.net/test/read.cgi/tech/1191875993/

283 :デフォルトの名無しさん:2011/09/28(水) 10:01:26.13
ある言語が関数型であるか否かを判断できる基準はあるかな?たとえば、
(1) 条件判定式(if/case式)がある
(2) 局所宣言式(let/where式)がある
(3) 末尾再帰の最適化
これらすべてを満たせば、大半の人には関数型であると同意してもらえると思う。
ML/Haslell/Schemeはすべて満たすから文句無し。(ただしLispは(3)がNG?)
Smalltalk/Rubyは(1)のみで、Python/JavaScriptは全滅だから関数型とは認められない。

295 :デフォルトの名無しさん:2011/09/28(水) 13:46:33.23
Python??2.5でif式(三項演算子)が入ってる

298 :デフォルトの名無しさん:2011/09/28(水) 16:13:01.13
Perlの無名関数はラムダとして認められないの?

300 :283:2011/09/28(水) 17:09:22.56
>>295
確かにif式はあるけど、Pythonのif式ってすごく特異というか汚い構文ですよね。
 value = then_value if predicate else else_value
たとえば条件判定がネストした処理をコード化した場合、SMLだと
 val value =
   if x == 0 then (
     if y == 0 then
       1
     else
       2
   ) else (
     .... 省略 ....
   )
同じ処理をRubyなら
 value =
   if x == 0 (
     if y == 0
       1
     else
       2
     end
   ) else (
     .... 省略 ....
   )
と、ほぼ類似のコード構造で、しかも適切なインデントで記述できます(=可読性のある記述ができる)。
SchemeとSmalltalkは構文が異なりますけど、これらの言語でも適切なインデントでコード化できます。
でも、このPhytonの構文だと、(自分の知識では)可読性のあるコードが書けないと思います。いかがでしょうか?


308 :デフォルトの名無しさん:2011/09/28(水) 19:22:34.24
>>283
そもそも、ある言語が関数型であるか否かを判断する「理由」はなに?

関数型であるか否かを判断する必要があるのってどういう場合?

314 :283:2011/09/28(水) 20:33:17.09
>>308
正直言って、あまり考えていないです。
「「分ける」こと「わかる」こと」という分類学の本(講談社学術文庫)がありますけど、
関数型であるか否かを考えることで関数型言語とは何かを理解しようとしているだけです。

あえて言えば、局面に応じた言語の使い分けですね。
デフォはRuby、でもここはSMLでも書き直そう、ただここだけはHaskellのほうが直感的に書ける....というふうに。

318 :デフォルトの名無しさん:2011/09/29(木) 00:39:55.69
「問題を解決する為に数学的な関数を構築する」

これをするプログラミング言語が関数型言語であり、これが本質です

それ以外の末尾再帰最適化や条件判定式、局所宣言式など諸々は全て、
個々のプログラミング言語が個々の目的の為に加えた飾りです
IOへのアクセス手段も、外部ライブラリへのアクセス手段も飾りです

それが実用かどうかは、関数型言語かどうかとは一切関わらない別問題です

100%この本質だけでプログラミング言語が作られている訳ではもちろんありません
ですが、基本理念としてこの本質を据え、その上でこの本質が活きるよう、
できるだけ壊さないよう、実用や教育(や遊び?)といった目的に応じて飾りが加わります

本質を忘れると、本質を活かすように加えられた飾りを上手く活用できません
本質を忘れると、馬鹿な考えに至ったり、関数型プログラミング言語で問題を解決することが
非常に困難になります

「関数型の特徴を取り入れた」と一般的に言っているのは本質を忘れた馬鹿な発言のいい例です
それは、ある複数の関数型プログラミング言語が共通して持つ「便利な飾り」を、
取り入れ先のプログラミング言語に合うように仕立て直したというだけのことです
本質を考えれば、関数型言語としての特徴を取り入れた訳では全くないことが分かります

334 :283:2011/09/29(木) 18:17:12.26
>>298,323

FP
 ---- 壁0. 変数の壁 ----
Haskell
 ---- 壁1. 純粋性(副作用)の壁 ----
SML/OCaml/C++11
 ---- 壁2. 型推論の壁 ----
Scheme
 ---- 壁3. 末尾再帰最適化/局所定義式の壁 ----
========<< 越えられない壁 >>========
Smalltalk/Ruby
 ---- 壁4. 条件判定式の壁 ----
Perl/Python/JavaScript
 ---- 壁5. クロージャ/ラムダ式の壁 ----
========<< 越えられない壁 >>========
C/C++/Java...etc

336 :デフォルトの名無しさん:2011/09/30(金) 20:14:01.41
条件判定式の壁ってのが相変わらず分からん

340 :283:2011/09/30(金) 21:23:28.76
>>336-338
条件判定が式として自然な形でコード化できるよう言語が設計されているか否か?という意味です。
誰もが関数型言語だと認める言語(>>334の最上段)であれば、当然これを満たしています。

Perl/Python/JavaScriptは条件判定(ifやcase)が(式ではなく)文として定義されているのでNGになります。
Pythonについては、if式はあるけれど「実用性に欠ける」設計であると判断しました。(>>300を参照)
もし value = if predicate ":" then_value else else_value という構文であればOKにしたかったのですが....。

# あくまで「俺様流判定基準」なので、納得いかないという意見が多々あることは承知してます

361 :デフォルトの名無しさん:2011/10/06(木) 00:33:33.17
>>318
> 「問題を解決する為に数学的な関数を構築する」
>
> これをするプログラミング言語が関数型言語であり、これが本質です

というような恥ずかしい大袈裟な言葉を平気で書けるのは、
君が関数プログラミングについて何も分かっていない事の証拠だね。
そもそも「数学的な関数」という言葉が何を表すかを理解せずに使ってるんだろう。

普通に数学で言う「関数」と関数プログラミング言語での「関数」は全然違う。
せめて学部レベルでも数学を専攻してちゃんと勉強した人間ならば
関数プログラミング言語での「関数」が数学での関数とはかけ離れた概念だと気づく筈だ。
そんな基本中の基本すら理解していないから上の引用箇所のような事を平気で書けるんだろうが。

364 :デフォルトの名無しさん:2011/10/06(木) 01:18:36.50
>>361
> 普通に数学で言う「関数」と関数プログラミング言語での「関数」は全然違う。
> せめて学部レベルでも数学を専攻してちゃんと勉強した人間ならば
> 関数プログラミング言語での「関数」が数学での関数とはかけ離れた概念だと気づく筈だ。

そんなことはない。
ラムダ計算が何のために作られたのか知らないのか?

ラムダ計算のみに依拠するようなら純粋な関数型言語(Haskellは理念的にはほとんどそう)の関数は、数学上の計算可能な関数と同じもの。

384 :デフォルトの名無しさん:2011/10/07(金) 00:02:40.48
>>364
> そんなことはない。
> ラムダ計算が何のために作られたのか知らないのか?

そんな事は百も承知だ。

> ラムダ計算のみに依拠するようなら純粋な関数型言語(Haskellは理念的にはほとんどそう)の関数は、数学上の計算可能な関数と同じもの。

まず普通の数学、つまり数学の主流分野の代数学・幾何学・解析学で登場する関数つまり写像は計算可能である必要はないし
存在しか主張できない写像はいくらでも登場する。数学の主流分野では「計算可能」なんて条件はほとんど無意味。
君が言っている「数学上の」の「数学」は数学基礎論という普通の数学からは相手にされてない数学の辺境の中でも
辺境中の辺境の再帰関数論部落や証明論部落の住民が考えている「数学」だ。
数学基礎論でも普通の数学と多少は繋がりのあるモデル論部落や公理的集合論部落になればすぐに計算可能とは限らない写像が現れる。
最も簡単な例は選択公理が存在を主張する選択関数だ。

更にλ計算はindefiniteに対する関数値とある変数をパラメタとする関数そのものを厳密に区別する表記法としてのλ記法での「関数値の計算」が
どういう事なのかを分析する為に、λ記法を純粋に構文的な体系として形式化し対象化したものだから、
λ計算での計算はreductionという純粋に構文的な概念のみだ。

ところが関数プログラミング言語で実際に行われている計算は必ずしもそうではない。少なくとも純粋に構文的なものとして理解しようとすれば
気がおかしくなりそうな計算メカニズムを用いているケースは珍しくない。グラフ簡約とかな。

数学をせめて学部レベルほどもちゃんと学ばずに基礎論の解説か通俗書をチョイと齧ったぐらいで「数学上の」なんて言い切らない方がいいよ。


391 :デフォルトの名無しさん:2011/10/07(金) 09:47:34.55
>>384

> まず普通の数学、つまり数学の主流分野の代数学・幾何学・解析学で登場する関数つまり写像は計算可能である必要はないし
・・・
> 最も簡単な例は選択公理が存在を主張する選択関数だ。

この部分は、数学でいう関数には計算可能でないどころか、存在することしか分からない関数もある、ってことだよね、要は。
それはそうだけど、それがなんで

> 普通に数学で言う「関数」と関数プログラミング言語での「関数」は全然違う

という言明を正当化するのか分からん。数学でいう「関数」の全部を扱えなくとも、その一部を扱えていれば十分じゃん。

加法と乗法しか習っていない小学生の使う自然数は、大学生の使う自然数とは別のものなのか?
もしそうだというなら、それこそ、過度に数学基礎論的な見方だと思う(嫌いではない)。


> ところが関数プログラミング言語で実際に行われている計算は必ずしもそうではない。少なくとも純粋に構文的なものとして理解しようとすれば
> 気がおかしくなりそうな計算メカニズムを用いているケースは珍しくない。グラフ簡約とかな。

グラフ簡約はいいだろ。
数学者が証明過程でいちいち論理学レベルの変形を事細かに書かないようなもんだろ。


数学基礎論を悪し様に言いつつも、オマエの言っていることには数学基礎論的な潔癖性を感じる。

404 :デフォルトの名無しさん:2011/10/10(月) 19:02:16.93
>>391
> > 普通に数学で言う「関数」と関数プログラミング言語での「関数」は全然違う
>
> という言明を正当化するのか分からん。数学でいう「関数」の全部を扱えなくとも、その一部を扱えていれば十分じゃん。

数学での関数概念は外延的。
プログラミングでの関数概念は内包的。

405 :デフォルトの名無しさん:2011/10/10(月) 19:12:12.84
>>404
> 数学での関数概念は外延的。

アホ?

491 :デフォルトの名無しさん:2011/10/23(日) 02:38:45.93
たとえば、自動販売機の状態遷移図があったとして、それを実装しようとした時、
OOP なら素直にクラスを作って、素直に状態遷移の処理が書ける
デザインパターンにもあるくらいだし

一方、これを関数型で実装しようとすると、状態遷移図の読み取ってから、
それをコードに落とすまでに、素直に作業が進むとは言いがたいと思う
(実際にそういう経験が多々ある)
図ではそれぞれの状態は分かれて書かれているのに、
関数型のコードにすると局所化されずに関係が全体に広がってしまう感じ

なんていうか、図とコードの一体感が薄い

OOP だって図とコードが一対一に対応しているわけでは決して無いんだけど、
OOP の場合は他人のコードを読んで、それを逆に状態遷移図に起こすことも、
そのコードが元々ちゃんとした状態遷移図からコード化してるのなら比較的素直にできる
それくらいには図とコードの一体感がある

関数型の場合、それが難しいと感じるケースが多い

状態遷移自体は必要なのだから何らかの図は必要なのだが、
今までの UML の状態遷移図が関数型にフィットしていないのか、
それともそれを関数型のコードに落とす手法に問題があるのか、
それとも単に私がまだまだ未熟なだけなのか

493 :デフォルトの名無しさん:2011/10/23(日) 05:59:43.71
状態という考え方と関数型プログラミングとは馴染まないんだよ。
そもそも状態遷移をガンガン使うって事は変数の値を次々に書き変える事で処理を進める手続き的パラダイムで考えてるって事だからね。
もちろん、そういうパラダイムの処理を関数型でシミュレートする(状態を表す引数を次々に渡す)事はできるが、
本来の関数型のパラダイムはそういう変数への破壊的な代入(バインディングとは等価でない代入)を避けるべきだという哲学に基づいているから
馴染まなくて当然だし、そういう状態遷移の処理を書くのならば関数型よりも手続き型の方が自然に書けて当然なんだよ。

494 :デフォルトの名無しさん:2011/10/23(日) 08:26:39.32
>>491-493
お前らにまとめて聞きたい
お前らはCのような手続き型言語であれば状態遷移機械を書けるのか?
実は書けない、あるいは今まで書いた事が一度も無いんじゃないのか?
情けない奴ら、お前らの将来はIT土方一直線で決定だ

反論があるなら、その前にまずWikipediaでトピック「有限オートマトン」にある
数学モデルの節を読め
ここではトランスデューサ型で決定性オートマトンだけを見ればいい
面倒であればトピック「ミーリ・マシン」を直に見てもいい

これだけ簡潔な数学的定義があるのに、まだ難しいとか馴染まないとか言うつもりか?!

510 :デフォルトの名無しさん:2011/10/23(日) 12:10:59.72
たとえば状態Aと状態B、状態Cがあるとする
今状態Aであるときにイベントxが起きたら、
状態Aが保持してる内部の変数の値とxで計算して、
その結果yをまた状態Aの内部変数に格納する
yの値によって次に状態Bか状態Cへ遷移する

こういう場合、OOP なら素直に状態毎にクラスを作る
あるいは一つのクラスのインスタンスを状態毎に作る
で、状態Aを表現するインスタンスのメンバ変数は、
そのインスタンスの中で完結していて外に出ることはない

一方、関数型でこれを実現するとき、
「状態を引数に入れて、計算して、戻り値として状態を返す」
ということを(再帰的に)繰り返すという方法をとると、
状態Aの内部変数に相当する値も色んなところへ運ばれる事になる
そうしないと、また状態Aに戻った時に計算できない

また、Haskell の State モナドのような仕組みを使っても同じ
本来は内部に閉じ込めておくべき情報が外に出ることに変わりはない

たとえ何らかの方法で、状態Bや状態Cの計算をしてる時には
状態Aの内部変数に相当する値にはアクセスできない仕組みがあるとしても、
その仕組みを作っている時は、色んなところへ情報が漏れることを
ちゃんと意識してプログラミングする必要がある
(一般的な OOP ならその仕組みは改めて作る必要は無い)

また、状態Aの計算の最後に状態Bを末尾呼び出しする方法は、
状態間の繋がりがますます強くなる

情報の漏れと結合度の強さ、これらをもう少し改善する方法はないだろうか

513 :デフォルトの名無しさん:2011/10/23(日) 12:17:44.03
>>510
> 一方、関数型でこれを実現するとき、
> 「状態を引数に入れて、計算して、戻り値として状態を返す」
> ということを(再帰的に)繰り返すという方法をとると、
> 状態Aの内部変数に相当する値も色んなところへ運ばれる事になる
> そうしないと、また状態Aに戻った時に計算できない

ん??? ここが不可解
それって、あなたがいっているOOPでも、状態Aから状態Bに遷移しても「状態Aのインスタンス」を保持しておいて、状態Aに戻ったときにそれを復帰させるってこと?

それはもう状態マシンの設計として破綻してない?
なんか、状態マシンと別の何かをごっちゃにしているような・・・

557 :デフォルトの名無しさん:2011/10/26(水) 01:47:25.32
GUIは状態が基本だし関数型は部分の開発効率向上寄与にとどまるよ

643 :デフォルトの名無しさん:2011/12/14(水) 14:12:31.00
関数型言語でもスパゲッティになる(ならざるを得ない)場合はあるでしょう。
自分が使っているコードにもそういう場所があって、反省してみると、
データの再帰的な定義に逆らうかたちでアクセスする場合に起こりがちな気
がします。

例えば、リストのリストを行列見立てて、アクセスすることを考えます。
(例えば、条件を満たす要素をnを取り出すなど)
val xss =
[ [1.0 , 2.0, ~3.0, 4.0]
, [~10.0, 20.0, 30.0, 40.0, 50.0]
, [100.0, ~200.0, 300.0]
, [1000.0, ~2000.0, 3000.0, 4000.0, 5000.0, 6000.0]
]

このときに、列方向(内側のリストに沿って)アクセスする場合は、
要素への操作をfとして
app (app f) xss
と簡潔に書けますが、行方向にアクセスする場合にはかなり複雑に
なります。

694 :デフォルトの名無しさん:2012/03/02(金) 00:25:01.03
関数型言語でWebのシステムは作れますか。
何か実績はありますか。

712 :デフォルトの名無しさん:2012/03/03(土) 15:59:16.17
なんで人はモナドで躓くんだろ?

748 :デフォルトの名無しさん:2012/03/04(日) 15:57:11.86
readFile :: FilePath -> IO String

なんで戻り値が String にならないの?
という初学者の素朴な質問にどう答えられるか。

749 :デフォルトの名無しさん:2012/03/04(日) 16:14:09.93
>>748
参照透過性が保証できないから

これくらいは初学者用の入門書に必ず書かれていると思うが

751 :デフォルトの名無しさん:2012/03/04(日) 16:25:13.92
>>749
答えになってないような。
IO String 型だとどうして参照透過性が保証できるの?

754 :デフォルトの名無しさん:2012/03/04(日) 17:09:44.62
>>751
逆だよ

readFile 関数が内部で行うことが参照透過性を保証できないから、
String 型ではなく IO String 型を使用させるを得ない

readFile 関数が参照透過性を保証できるのなら String 型を使ってる


なんで readFile 関数が内部で行うことが参照透過性を保証できないかと言えば、
引数である Srring 型のある値に対して、戻り値として返す String 型の値が
いつ如何なる時でも同じ値になるとは限らないからだ

それは、例えば読み込むファイルの内容が一時間前と変わっているかもしれないから
そうなれば同じ引数に readFile 関数を適用しても、戻り値が同じにならない

同じになる場合もあれば、ならない場合もあり、同じだという保証ができない

800 :デフォルトの名無しさん:2012/03/06(火) 00:00:43.39
素朴な疑問なんだけど
lazy eval な処理系って realtime なシステムに適用可能なの?


862 :デフォルトの名無しさん:2012/08/19(日) 21:34:24.06
最近の手続き型は関数型の一部を取り込む例がありますが、
逆はどうなんでしょう?


866 :デフォルトの名無しさん:2012/08/19(日) 22:39:26.00
>>862
そうそう、C言語は(手続きが無くて)関数だけでプログラミングするから関数型言語だよな

...... こうですか?よくわかりまへんw

869 :デフォルトの名無しさん:2012/08/19(日) 23:15:07.57
>>866
C#のラムダ式とか


http://toro.2ch.net/test/read.cgi/tech/1252470706/l50/../人気ブログランキングへ