1 :
デフォルトの名無しさん :
2011/11/08(火) 18:06:57.51 関数型言語は学習コストが高すぎる。 玩具として、研究者や学生の自己満足として、 教科書や黒板を賑わすアクセサリーとして、 あるいは頭の体操としての価値は認める。 だが、仕事ではほとんど使い物にならない。 やれば作れる、実際に作った、そんな言い分は聞き飽きた。 主要なソフトウェアのほとんどは非関数型で書かれている。 関数型がプチブームだが、爆発的に採用が増えているとも考えられない。 いずれ関数型のブームは去るだろう。 仮に関数型が生き残ることがあったとしても、 手続的な言語における一部の機能としてだろう。
はいはい アイちゃんアイちゃん
バカに教えようとしたのがまずかったんだ
人間の日常的な思考は全く関数的でない。 業務の手順等も全く関数的でない。 「まずこれをやって、それからこうして、 それでこうなるから、これをこうする」的な考え方をするのが普通の人間。 もしそれを自動化するプログラムを書こうとした場合、 それを素直に書ける言語のほうが普通は楽にできる。 仮に関数型のほうが簡潔に書けたとしても、 関数型に脳内変換しなければならない時点で負担は大きい。 関数型なら生産性が向上するという主張は、 一部個人ではそういうこともありうるが 社会全体としてはむしろ生産性の低下につながる。 関数型が使えないのは頭が悪いからだというのは、まぁある程度正しい。 だったら頭の良い人が自己満足で使っていればよいのであって、 他人様を巻き込む必要はない。
京都大学霊長類研究所では、未知の感染症が蔓延し、 感染した研究員はどのスレッドにも同じコピペを 繰り返すといった症状が報告されています。 研究員によると思われる書き込みがあっても 近づかないようにしてください。 京都大学
6 :
デフォルトの名無しさん :2011/11/08(火) 19:09:22.90
7 :
デフォルトの名無しさん :2011/11/08(火) 19:12:56.72
時々の状態を覚えておかないといけない クライアントアプリケーションに関数型の適用は不適切だと思う Webサーバアプリは大きく見ればフィルタと見なせるから 組みやすさは別として関数型が使える分野だと思う 使ったことはないが
流行るということは馬鹿と貧乏人が手を出すということだ よって関数型言語は流行りようがない
黒板とな
>>1 流行らないから安心しろ。
分かる人間だけが細々と使っていき、その成果が手続き型に取り込まれていくだけ。
もし流行るなら、もっとマシな世界になってる。
このスレッドは天才チンパンジー「アイちゃん」が 言語訓練のために立てたものです。 アイと研究員とのやり取りに利用するスレッドなので、 関係者以外は書きこまないで下さい。 京都大学霊長類研究所
>>1 スレタイ間違ってるよwww
誤:【アンチ】関数型言語は使えない【玩具】
正:【アンチ】関数型言語が使えない【玩具】
>>1 CやRubyより覚える事少ないと思うんだが。。。
というか
>>1 は関数型言語を知ってる側の人間だろう
>>12 ,14
>>1 は典型的なハスケラ症の患者
>366 名前: デフォルトの名無しさん Mail: sage 投稿日: 2011/10/26(水) 12:25:43.06
>
>>365 >それはハスケラ特有の症例で、心の病の一つ
>
>ハスケルという言語を使っていると、世の中のあらゆる事柄すべてが
>ハスケルを中心に廻っているように見えるらしい
>従って、あらゆる関数型言語は静的実行かつ静的型付けでなければならないし、
>遅延評価が常識であり、一切の副作用は認めようとしない
>
>ハスケラにとって関数型言語とはハスケルのことであり、
>その窓から見える世界が彼らのすべて
誤:【アンチ】関数型言語は使えない【玩具】
正:【アンチ】ハスケルは使いものにならない【玩具】
代数の基礎を一応は学んでいる理工系の人なら自然だと思うが プログラム書くのはそういう人達だけじゃないからな
OCamlだけは認める。
>>16 一次関数二次関数習ってれば、十分覚えられるだろ
感情的な毛嫌いをするような人たちに彼らの能力の対極 にある言語を使えるわけがないわな。
>>13 学習コストと暗記量は比例しない。
覚えることが少なくても
使いこなすのが難しければ
学習コストは高い。
かつてのプリントごっこで出来る事はプリントごっこでやればいいし、印刷機必須のものをプリントごっこでやろうとすると悲惨なことになるのと同様。
>>20 使いこなす事も簡単だと思うけど。。。。
自分、yesコマンドとか、haskellでは作れても、Cやrubyで書けへんねん
>>22 無限ループ内でひたすらyes\n出力してフラッシュじゃだめなん?
ruby -e"begin; loop{puts ARGV[0] || 'y'}; rescue Interrupt; puts; exit 0; end" こんな感じ? 恥ずかしながらyesコマンドって初めて知った
まあ、シェルスクリプトですら滅多に使わないからなあ
>>25 ごめん。
たぶん、作れる。
作り方もそれで合ってると思う。
確実に作れないのはクイックソートをCでは作れないなw
配列でってだけで、どうすれば良いのか分からんw
昔、Cのクイックソート読んだけど、全然何やってるのか分からんかったwww
>>26 Haskellの入門書(日本人の書いた「入門Haskell」の方)に乗ってて、ちょっと前に、コマンドライン版じゃんけんゲームのテスト用に思い出しながら書いた
じゃんけんゲームは別にCでもRubyでも書けるんだけどね…
29 :
デフォルトの名無しさん :2011/11/12(土) 15:55:12.09
>>24 別に間違ったことは言ってないだろ。
Common LispのほうがSchemeより使いやすいと感じる。
Schemeは覚えることは少ないが、理論に走りすぎ、
ミニマム主義が度を越していて、再帰を強要しすぎで、
実用性ではCommon Lispより劣る。
Common Lispは関数型のような手続き型だと言えなくもないが、
あれくらい節操が無くて何でもありのほうが
過剰にテクを要求されないので書きやすい。
ハスケルって学校の実習でしか使われてないんでしょ?
>関数型が使えないのは頭が悪いからだというのは、まぁある程度正しい。 >だったら頭の良い人が自己満足で使っていればよいのであって、 そのロジックなら「頭の良い」人が集まる会社は関数型を使うべきだよね 個人的には、その意味で「頭の良い」人はプログラマ人口の50%を超えると思う
>>31 > そのロジックなら「頭の良い」人が集まる会社は関数型を使うべきだよね
え?その論理能力で関数型分かってるとか自称するの?
対偶を取っても、「頭の良い人は関数型を使える」であって、「使うべきだ」にはならんぜ?
>>32 書いてからそれ思った
言い訳をすると、使えるなら使う方が良いというのは
「だったら〜使っていればよい」から読み取れないこともないよね
>>33 色々な言語や環境を使ってみて自分で評価するのは大事なことだよね。
でも、「使うべき」という言葉からは、微妙に排他的なニュアンスを感じなくもない。
昔のオブジェクト指向もそうだったけど、これから盛り上がろうという言語や環境は
得てして独善的になったり排他的、攻撃的になったりしがちだから、
気をつけたほうがいいかもね。
>>34 俺自身が「使うべき」と主張してる訳じゃないからな、一応言っておくと
>>35 あ、すまん、勘違いしてた。吊ってくるわ。
>>34 誤った用法:
>これから盛り上がろうという言語や環境は
>得てして独善的になったり排他的、攻撃的になったりしがちだから、
正しい用法:
>ハスケラは
>得てして独善的になったり排他的、攻撃的になったりしがちだから、
それは「正しさ」をウリにしているパラダイムの宿命かもなw ただし、Haskellのコードが本当に正しいのかは疑問が残る。 証明うんぬんとか言うが、全てのコードが正しさを証明されているわけじゃあるまい。 ましてや、仕様自体の無矛盾性まで証明されているわけでもあるまい。
いわゆる関数型っていうより宣言型の趣きが強い言語はキツイ
関数型はコードが美しいけど、オブジェク指向は構造が美しい。 ツールでUML生成してニヤニヤするのがいいんじゃないか
UMLってなんかおっさん臭い印象がある。
Haskellを実プロジェクトに使うのは現状無理だな メモリ消費が予測不能すぎ ML系のほうが扱いやすいよ
金融周りのツールで使われてるイメージ。あとはtwitter。 ってか、関数型のメリットってオブジェクトを持たない(状態を持たない)から 変数周りでバグが出にくいってメリットがあるんじゃないの? 後は型推論とか可読性とか javaが読み辛いすぎるだけの気もするけれど
関数型言語ってそもそも入出力どうしてんの DB操作とかどうすんの
関数型言語で tail -f って書けるの?
Hello, worldができるんだから同じ要領であらゆる入出力ができるし、Cも呼べる
>>47 君がstatもselectもepollも使ったことがないのは分かった
は? もしかしてC関数にポインタを渡せるかを心配してるの? HaskellやOCamlなら当然できるよ
>>46 てきとーに書いたら手続き型っぽいコードになった
let rec tail_f filename where =
let c_in = open_in filename in
let size = (Unix.fstat (Unix.descr_of_in_channel c_in)).Unix.st_size in
seek_in c_in where;
Stream.iter print_char (Stream.of_channel c_in);
flush stdout;
close_in c_in;
Unix.sleep 1;
tail_f filename size
let tail_f filename = tail_f filename 0
let _ = tail_f "foo.txt"
>>51 せめてfilenameじゃなくてc_inを渡す感じにすりゃいいのに。毎回opencloseする意味ないし、selectで待機できるだろ
「関数型言語で手続き型言語っぽい記述もできる」 「手続き型言語で関数型言語っぽい記述もできる」の両方が真なら、 本質的な違いは制約の多さだけだな。
手間掛ければまあ何でも出来る 細部が重要だ 破壊的代入のたびに一々 := だの ! だの書く気にならなんよ
>>53 どうしてこんなキーワードがあるの?
http://d.hatena.ne.jp/kazu-yamamoto/20080904/1220495854 より、引用を抜粋(ややこしいw)
ちゃぶ台をひっくり返すようなまとめ
「なぜ Haskell は重要か」の一部を翻訳して、この記事のまとめとします。
(関数型言語と)同じ程度とは言えないが、命令を並べる方式でも抽象化していくとこはできる。
命令型言語では、新しいキーワードと標準ライブラリを導入することで抽象化する。
たとえば、多くの命令型言語は、プログラマーがループを実現する仕事から解放されるように、少しずつ動作が異なる複数のキーワードを用意している。
しかし、命令型言語は、命令を並べる方式に基づいているため、そこから完全に逃れることはできない。
命令型言語では、命令の並びに対し、抽象化のレベルを上げる唯一の方法は、さらなるキーワードや標準関数の導入である。
そして、言語はゴチャゴチャになる。
引用を抜粋、終わりw
まさに、OOPの事だな。
http://codepad.org/0WvSpM7o のコードでは、dataと、deriving (Eq,Ord,Show,Read)、あと|(OR演算子だったり、ガードだったり)以外は、言語としてのキーワードは使ってない。(機能としては、パターンマッチも使ってるけど)
そのまま、数学の定義を持ってきてるだけ
手続型言語だと、キーワードはこんなに少なくできない
あ、==もか まあ、キーワード少ないのは変わらないか
>>55 制御構文がムダに多いのは自然言語もそうだし、別に問題ないだろ。
制御構文が異常に多くなって呪文みたいになった言語なんてPerlくらいしか知らんよ。
>>52 関数型とか関係なくselectじゃ待てんだろ
>>57 そうは言うが、例えばRubyの入門書を読んだだけでは
>>55 と同じ動作のコードを書けるようにならない。
入門書では、Haskellと同じ抽象度を表現できるキーワードが揃ってない事になる。
が、このコードはプログラミングHaskellという入門書を読破もしてない自分が書いたものだ。
この差は、何だろうな。
一方で、副作用のある処理をしようとすると、HaskellでもHoogleなどで調べる回数が極端に増える。
関数型でも手続型でも、副作用がキーワードを生んでいる。とも言えるのかもしれない。
>>58 は本当に入出力を知らないんだな…。
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
最後の引数が何か分かるか?
>>59 は TMTOWTDI とか聞いたこともなさそうだ。
これから
>>60 がselectでtail -fを書くスレになりました
>>62 GNU coreutils のsrc/tail.c が実例だ。 俺が書く必要はかけらもないな。
selectで待機できるのはパイプやソケットやpty等であって 通常のファイルには役に立たない (ファイルの終端に達してもファイルディスクリプタは読み取り可能として扱われるから)
>>1 プログラマは資格もなにもいらないから能力のない奴がいっぱいいる。
言わばヤブ医者がいっぱい病院立てている状態。当然頭のわるい奴には
最新の医学なんて理解できないからいつまでも古い治療法を続けている。
そんな状態では高度な医学は流行っていないと観測される。
おれはどんなに少数派でも最新の医学を理解している医者のいる病院にいきたいな。
じゃあその最新の医学とやらの例を挙げて欲しいな 名ばかり最新では困ります
>>303 2chも書き込むのに資格が要らないんだが、気付いて無かったようだ。
関数型が広まらないのは、難しいからじゃなくて 「OOP?デザインパターン?馬鹿じゃねーの?www」って雰囲気を 醸し出してるから。 そりゃ関数型言語以外のプログラマには反発されるよね。
OOPって呼び方なんとかならないか 俺英語の感覚が染み付いてるからウープって読んじゃうわー 俺英語の感覚が染み付いてるからー
>>69 ああ、本物のプログラマーは・・・とか、そんな感じのね
本当は、初心者でも割と簡単に複雑なプログラム組めるのにね・・・
初心者がいきなり初日にLength関数作れる言語って、Haskellに限らず、(多分)関数型言語だけだよ
C#でも多分作れるぞ
そんな情緒的なことで決まるか? ○○は仕事で普通に使うこれが仕事の標準の道具だ。 ○○は豊富なライブラリが揃っていて環境もある。おまけに、つかいては わんさかいる。 こんなところだろうよ。
It is true that OOP is oops! :-)
>>69 誤:関数型が広まらないのは、難しいからじゃなくて
「OOP?デザインパターン?馬鹿じゃねーの?www」って雰囲気を
醸し出してるから。
そりゃ関数型言語以外のプログラマには反発されるよね。
正:ハスケルが広まらないのは、難しいからじゃなくて
「OOP?デザインパターン?馬鹿じゃねーの?www」って雰囲気を
醸し出してるから。
そりゃハスケラ以外のプログラマには反発されるよね。
手続き型スタイル def length(x): n = 0 while x != []: n += 1 x = x[1:] return n 関数型スタイル(?) def length(x): return reduce(lambda n,_: n + 1, [0] + x)
そもそも、手続き型言語でリストのLengthを実装したいと思ったことがない件。
javaでいうcollectionくらい使ったことがないの?
>>78
>>79 size()メソッドが既にあるだろう。 使うだけならなんで自分で実装する必要があるんだよ
length xs = sum [1|_ <- xs] def length(xs): return sum([1 for _ in xs]) カレーの圧勝だな
関数型言語では遅延評価があるから、集合のlengthを求めるのに再帰が必要って話を そもそも再帰しなくても標準ライブラリでデータのリストを扱う手続き型言語にもってくるから話がおかしくなる。 手続き型言語が持ってる、集合の最もシンプルなインタフェースは Javaでいう Iterable だろうが、Javaでこれを生で扱う機会がそもそも多くないからな。
reduceやリスト内包やsumを使ってて 再帰なんて使ってない件
>>83 全要素のスキャンを行ってるのは同じだろうに。
組み込み演算子ならOK、って理屈は、javaなら標準ライブラリにsizeがあるってのとどう違うんだ?
情報科学業界の知人らに C#er なので 再帰はなるべく避けようと思います っていったら何言われるかわからなくて怖い
・Haskellプログラマ lengthはあくまで一例であって、そういう機能を自分で実装する際に どれだけ楽に書けるかに注目している。 ・Javaプログラマ 標準ライブラリにsizeがある、で思考停止。 基本的にライブラリの機能を呼び出す事しか考えないドカタ気質。
c#はx86とx64,DebugビルドとReleaseビルドで末尾最適化の有無が変わる恐ろしい世界
>>86 よく分からんけど車輪の再発明が好きなの?
lengthって例が適切ではないのを棚に上げて
>>88 ライブラリに無い機能があったらどうする?という当然の可能性を考慮できないのがドカタ。
前にどこかのスレで見た、下のコードのJava版は冗長すぎて笑ったwww pyths n = [(x,y,z) | x <- [1..n], y<-[1..n], z<-[1..n], x^2+y^2 == z^2]
こういう対立は収束するまで関わりたくないので vimとかemacs とかいじってます
>>91 楽しい言語スレだね
書き出しは私
他の言語だとどうなん?って聞いたらScalaやOCaml、Python、Javaが出た
Rubyが真っ先に来ると思ってたけど、結局来なかった
Rubyプログラマは勝てる(短く書ける)勝負にしか参戦しないよ 護身完成してるから
関数型は関数向きのコード書けると気持ちいいよね
>>86 int[] array = new int[100];
配列というのは当然、領域を確保する時にサイズを指定するわけです。
array.size() というものがなければ、どうやってサイズを取得するのでしょうか。
int getSize(int[] array) {
...
}
この関数を再帰でもループでも、size() を使わずにどうやって書きますか?
教えてください。
int[] array = new int[100]; int n = 0; for (int i: array) n++;
その for の停止条件に size が使われています。
つまり、
>>97 はこれと等価です。
int n = 0;
for (int i = 0; i < array.size(); i++) n++;
リストの size を再帰で書けるのは、最後に nil で止まるからですよね。 nil と cons cell がリストというデータ構造を定める基本要素です。 同様に、先頭番地と要素数が配列というデータ構造を定める基本要素です。
>>98 証拠は?使われていますと言われても納得できない
AbstractList$Itr.class public boolean hasNext() { return cursor != size(); }
おみそれいたしました。
>>96 関数型言語のは配列でもリストでもなく、要素の「集合」で、要素数は遅延評価になってる部分集合を評価して解決しないと判明しない。
手続き型言語のデータコンテナと比較するのがそもそも間違い。
>>104 横からツッコミを入れるけど、自分の知っている「集合」の定義とは、
・互いの要素は重複しない
・要素間に順序は存在しない
というもの
>>104 の言う関数型言語では、(リストではなくて)集合を直に表現できるの?
自分の知っている関数型言語(ML, Haskell)では、集合はライブラリとして実装されている
少なくとも、
>>77 ,81,91 のコードは(集合ではなくて)リストだよ
もしよろしければ、その(集合を扱える)関数型言語の名前を教えてくれ
重複可集合で要素数を明示的に持ってないってなんのメリットがあるの?
無限を表現できるというメリットがある このメリットは重複の可否や順序の有無に依存しない(無限リスト, 無限配列, 無限集合など)
>>55 OOPはキーワードを少なくできないって?
HaskellやML系よりSmalltalkのほうがキーワード数はずっと少ないよ。
関数型言語の人達がOOPを腐すときには大抵、OOPへの理解の浅さが見え隠れする。
これって、OOPの人達に迷惑なだけでなく、関数型言語の人達にとってもマイナスだよ。
>>71 > 初心者がいきなり初日にLength関数作れる言語って、Haskellに限らず、(多分)関数型言語だけだよ
そういう態度が反発を食っているということに気付かないのかなあ?
その論理でいうなら、初心者がいきなり初日にDriveACarを書けるのはLOGO系だけだよ。
でもそんなの当たり前だろ。その言語のパラダイムにドンピシャな例題出したって、恥ずかしいだけ。
>>91 効率悪いね。マトモなプログラマならMichener&Bresenham使うでしょ。
関数型言語の人って、O(n^2)のアルゴリズムがあるのにO(n^3)のアルゴリズムを平気で使うの?
リストが得意なのはわかったから、同じ方法でリングバッファを実装してみてくれ。 初日でリングバッファの実装できるかな? Smalltalkでは初日の初心者にも簡単に実装できたぞ。
>>111 恥ずかしながら、マージソートがどういう動きするのか分からなくて、アルゴリズムの本で期待される動きを見てからHaskellで実装できるという低レベルさなんだが・・・
リングバッファと言うのも、同じく知らない。
どういう動きを期待されてるものなの?
>>110 すまんね
マジで初心者なんで、まんま直感的に書いただけ。
効率的なアルゴリズムがあるなら教えて下しあ
>>110 関数型言語の人は1から順に指を折って数えないと、数字すら理解できないんだよ
ちなみに言うまでもないことだが、大半のコンピュータはビットベクタの並びをを数値として解釈するのとは大きく異なっている。
× 大半のコンピュータは ○ 大半のコンピュータが
>>113 let pyths n = [(a*a-b*b, 2*a*b, a*a+b*b) | a <- 1--n; b <- 1--(a-1)]
>>107 大きさ不定を表す場合は
size = -1を あてればいいじゃん
全要素対象の演算でループ回数を予測できなきゃ最適化できへんやろ
リファクタリングって関数型やってたら昔からあるふつうのコトだよね。 最初はラフにスケッチを作って、綿密に作品にしていく作業ということを グレアムが言ってるけど、そうゆう作り方は関数型じゃ普通だもんな。 十年以上も前のことを追いついて騒いでるだけって見えるよ。
>>119 お前、真性のおばか?
乱択アルゴリズムとか使ったことないの?
ダメだこりゃw
>>120 > 最初はラフにスケッチを作って、綿密に作品にしていく作業ということを
君はこれをリファクタリングと呼ぶのか。
たぶん、君は一生関数型だけを使っていたほうがいいよ。
たのむから他の言語は使わないでくれ。尻拭いする側の身にもなってみろw
うーん。。。 自分は、初心者じゃないプログラマがhaskell覚えれば、すごいものを簡単に作れるんじゃないかと期待してるんだが。。。
いま簡単な回路のシミュレータ作ろうかと思ってるんだけど haskell だと簡単? 組み合わせ回路、順序回路、配線それぞれに整数遅延を自由に設計でき コンストラクタで回路要素を一個10文字程度で定義 ワイヤードORはアリっていう仕様
>>124 >組み合わせ回路、順序回路
「プログラミングHaskell」に演習レベルのがあるね。
>>121 その方法はこれより速いの?
ちょっと書いてみてよ。このくらいなら簡単でしょ?
let rec range x y step = if x > y then [] else x :: range (x + step) y step
let pyths n = [(a*a-b*b, 2*a*b, a*a+b*b) |
a <- range 1 n 1;
b <- range ((a mod 2)+1) (a-1) 2]
let pyths_all n m =
let xs = [(k*x,k*y,k*z) | (x,y,z) <- pyths n; k <- 1--m] in
xs @ [(y,x,z)| (x,y,z) <- xs]
元コードが遅いことを認めたわけね。はい、ご苦労さんw
>>127 いや、元コード書いたの俺じゃねーし
で、ちょっとコード書いてみてよ
まさかFizzBuzzレベルのコードが書けないわけでもないんだろ?
ふーん、Michener&Bresenhamでググッてみた?
まさかコード書けないレベルの人間がこのスレに居るとは……
>>127 よく見ろw
HaskellじゃなくてOCamlだw
>>125 関数はMLしかわかりませんが...
回路一個=関数一個として
遅延がある時点で
任意の関数fは遅延Dfの数だけd * d通りの状態を持つ
ことと等価でないといけないはずですが(3入力ならd*d*d)
純粋な関数型じゃイメージしにくいです
(でないと順序回路や入力の変化に対応できないはずです)
Haskell で web application を書いた経験のある方いますか? とっかかりとして、apache module はあるのでしょうか。 mod_haskell は 0.1 だそうですが、これは安定しているでしょうか。
>>134 SMLでよければ、Programing in Standard ML に3ページほどの解説があるよ。
http://www.cs.cmu.edu/~rwh/introsml/ 高階関数と無限リスト(シーケンス)を応用した純粋な関数型プログラムで、
副作用は一切使われていない。コードはこんな感じ。
fun RS ff (S : wire, R : wire) =
let
fun X n = nor gate (zip (S, Y))(n)
and Y n = nor gate (zip (X, R))(n)
in
Y
end
回路シミュレーションならSICPの3章を見てみればいい。コツはわかる
138 :
デフォルトの名無しさん :2011/11/17(木) 17:23:01.92
関数型言語が強力で、大きな可能性を秘めているのは誰でも認める。 しかし、その割には衆人に受け入れられないし、 強力にアピールするようなものが生まれてこない。 関数型言語は簡単だと主張する人は、嘘を言ってるつもりはないだろう。 しかし、難しいと感じる人が実際に大勢いて、実際に社会で活用される機会を比較すれば 明らかに見劣りしているという現実は受け容れるべきだ。 全部S式で考えるから簡単だという意見も時々耳にするが、これは論外。 人間の自然な思考は手続型であり、それをS式思考に転換ことに成功すれば簡単だろうが 実際にその転換に成功する人は多くない。 だからこそ、広く受け容れられるに至っていないのだから。
仕方ないさ。違ったパラダイムのものを触るのは知らない時より コストがかかるんだから。純真無垢の何もしたことがない人と 手続きの育った人を比べると、素直な髪の毛と 寝ぐせがついた髪の毛をセットするときの違いのようなものさ。 要は、わからないようになった人って多くは寝癖。その寝ぐせが 作るときの中心になってんだから、保守的になるのは普通だよ。 squeak界隈でも、プログラマより子供のほうが理解が速いという事は あるらしいからね。 難しいと嘆くより、頭が硬くなって(あなたにとって)目新しいもの を否定する頭の硬さに老化の兆しを感じて嘆いたほうがいいと思うな。
F# がはやったら本気出す
手続き型言語が関数型言語を参考にし始めてる事の説明になってないので15点。
ちょっと取り入れるくらいがちょうど良い
>>141 関数型の良いとこ取りをしつつ、関数型の悪いところを無視してるってこと
良いとこさえ真似れば関数型そのものは用済み
CTMCPを知ってて言ってるんなら10点だな。
>>144 関数型はそーゆーのを知ってる人のための言語なのか
象牙の塔専用言語ということが証明されたね
#!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" proc mylength {x} { length2 $x 0 } proc length2 {x c} { if {$x == {}} { return $c } else { length2 [lreplace $x 0 0] [incr c] } } puts [mylength {1 2 3 4}]
147 :
146 :2011/11/17(木) 21:50:49.11
;length by Scheme (define (mylength x) (length2 x 0)) (define (length2 x c) (if (null? x) c (length2 (cdr x) (+ c 1)))) ;Schemeで書けばこうなる ;関数型は得意なことならスッキリ書ける ;関数型だから関数型らしいものだけ書けば無敵 ;普通のプログラマは簡単に窓を表示できたり、 ;テキスト処理に便利な関数や強力な正規表現が用意された言語を使えばいい
tclって末尾再帰最適化されるんだっけ?と思ったら schemeと比べるために末尾再帰にしたのか
代数DT, パターンマッチ, 高階関数、部分適用、オフサイドルール(任意) をそなえた手続き言語欲しい
にしてもCTMCPをやってる人って少ないよね。(ネットでは) 一部の読んだ人って大学の輪講とかで使ってんのかな。
CTMCP程度で挫折してたらこの先厳しいだろ。
インドから来てた短期研修生は知ってたな。 DB構築なんかも初めてのパッケージだとか言いながら、ネットで(勿論英語サイトを)調べながらちゃっちゃと組んでたw
>>152 複数のプログラミング言語を使った後に読んだが、計算モデルの意味が解って、その言語に適したコーティングをやり易くなった。
>>155 なるほど、僕も複数の言語使ってるけど、参考になります。その言語
言語で適した書き方あるもんね。
関数型言語って役に立つな。 スイスの海軍並に役に立つな。
>>155 適した書き方、もあるが
解決したい問題→どの問題領域か?→どの計算モデルが適しているか?→どの言語が適しているか?
の見極めが早くなるので、読んどいた方が後々楽。
勿論、「最適言語」にも幅があるので、効果/追加リソースが大きいのを選ぶことになる。
でも、それは問題解決というパラダイムに縛られた考え方。 プログラミングは問題解決型の領域だけじゃないぜ?
低スキルでもどの言語でも大差なく扱える問題は、自分の慣れた言語でやれば良い話だな。 世間の仕事の9割以上はそういった、単純な事務処理だから別に問題ではない。 その手の仕事だけやる分には、このスレに書きこむ必要もないだろう。
面白いよな。
問題解決領域を見極めた方法がわかりやすい本だよ
といえば、
問題解決のパラダイムに囚われた考え方。そんなんだけじゃないぜ?
と
どの問題でも大差なく扱える問題は自分でなれた言語でやれば良い話。
>>159 のサジェスチョンを全く理解してないってことだと思う。
>>163 問題解決パラダイムに染まりきってるね。
問題解決以外はどの言語でも大して変わらんとか、分かりやすいドカタ思考だ。
>>164 うーん。。。 この人って 問題解決パラダイムのこと書いてたら、
それしか頭にないと思う人だろうか?お気の毒な頭脳をお持ちなのね。
167 :
デフォルトの名無しさん :2011/11/18(金) 21:41:13.95
え?
>>165 一連の書き込みを、自分ともう一人だけがしてると思ってんじゃないかな?
>>93 Rubyで書いてみたいな…けどHaskellわかんないんだ
JavaとPythonなら分かるんだけど、どんなコードだったの?
久しぶりに社会に出たらC#が流行ってたのでやらされた。 C#にはnullとかいうのがあるらしい。 クソめんどうくさかった。
>>172 public static List<Integer[]> pyths (int n) {
List<Integer[]> list = new ArrayList<Integer[]>();
for (int x = 1; x <= n; x++) {
for (int y = 1; y <= n; y++) {
for (int z = 1; z <= n; z++) {
if (x * x + y * y == z * z) {
list.add(new Integer[] {x, y, z});
}
}
}
}
return list;
}
>>172 pyths n = [(x,t,z) | x <- [1..n], y <- [1..n], z <- [1..n], x^2 + y^2 == z^2]
177 :
172 :2011/11/20(日) 02:00:52.12
>>174 おk把握
def pyths(n)
(1..n).flat_map{|x|(1..n).flat_map{|y|(1..n).map{|z|[x,y,z]}}}.select{|x,y,z| x**2 + y**2 == z**2 }
end
こんなもんかなあ、Rubyだと。
これでもいい気はする。 def pyths(n) (1..n) .to_a .combination(3) .select{|x,y,z|x*x+y*y==z*z} end
179 :
172 :2011/11/20(日) 02:59:41.99
…Array#combinationとか初めて知ったぜ
180 :
デフォルトの名無しさん :2011/11/20(日) 06:49:14.50
なあ、そもそも俺はピタゴラス数を求めるプログラムにしか見えないんだが 結局、何を求めるプログラムなわけ? 関数型言語って人が見て何をやってるのか分からない言語じゃないのか?
182 :
デフォルトの名無しさん :2011/11/20(日) 19:57:20.80
内包表記と関数型言語の関係ってどう解釈したらいいんだろうね。
喫茶店で若いOL風の女性がCTMCP読んでて萌えた
そこで 俺のmozartでozozしないか?と聞かないと。意味不明
正直、174だろうが175だろうが、178だろうが それぞれの熟練プログラマが書いたら効率は そんなに変わらなくね? アセンブラとかなら変わるだろうけど 違うとしたら、178が何をやってるのか理解するのに勉強が 必要だというぐらいだろ
>>181 > 関数型言語って人が見て何をやってるのか分からない言語じゃないのか?
それは手続き型言語
手続きは 資材を並べていく感じ 関数は 資材を加工する機械に通してる感じ。
>>186 関数型は未だにパッと見でわからないです。
関数型は組み合わせ 手続き型は積み重ね
手続き型言語は古典力学 時間の流れは一方的、開いた系で現実的 関数型言語は量子力学 時間の流れは存在せず、閉じた系で理論的
手続きは乱雑 関数型は整理
手続き型は系列 関数型は羅列
>>174 元ネタが見つからないのでわからないのですが、int しか使わない縛りとかあったのでしょうか。
List<Integer[]> list = new ArrayList<Integer[]>();
for (int x = 1; x <= 100; x++)
for (int y = 1; y <= 100; y++) {
double z = Math.sqrt(x * x + y * y);
if (z <= 100 && (int) z == z) list.add(new Integer[] { x, y, (int) z });
}
>>193 それ、間違い。浮動小数点数の扱いに慣れてない?
すみません、わからないので教えてください。
なんだか、遂に、Ozまで流行りだした。
>>196 Prologには既にブームの兆しがあるし、関数型の周辺に
猛烈な勢いで関心が拡がって、渉猟されてる感がある。
199 :
205 :2011/11/21(月) 08:50:34.60
>>185 理解するのに勉強が必要って…どれも必要だろう
>>181 まんま、ピタゴラス数を求める関数でんがな
パッと見で分かってるじゃん
>>188 当然関数型でも解りやすいのと解りにくいのがある。
Perlの変態コードだってパッと見わからんでしょ。
それに手続き型に何年親しんでから、関数型をどれくらいやったのか?
単なる慣れの要素もある
>>200 その勉強量が違うだろ
多くの人が知らない概念を使ってる場合、
その多くの人は新たに勉強する必要がある
知ってる場合は勉強する必要はない
>>202 関数型でわかりにくいというのはどこを指してるのか?
(reduce .. (filter .. (map .. (map ....
もなぁーど ...
基本は再帰を乗り越えなアカンっていうのはある。関数型で
バッドノウハウだと思ってるのは、末尾再帰くらいかも。
ポイントフリーな書き方が出来るようになれば カッコも再帰も最小限ですむよ
206 :
デフォルトの名無しさん :2011/11/22(火) 16:09:47.64
>>205 ハスケルだったらね。ポイントフリーのほうが楽なこと多いよね。
あれで必要以上に複雑なことしなければ、誰だって使えるようになるでしょうよ。
関数型が分からん奴ってunlambdaでもやってんの?
ポイントフリーは難解
関数型が広まらなかったのは、ハードウェアの制限のせい 64ビットOSが普及すれば、スクリプトより楽な巻子型言語が普及・・・して欲しいなぁ… 関数型言語って、基本的に簡単だけど、要求スペックも無限のメモリ、無限のクロックなんだよね・・・ 通常アプリでメモリやクロック、スレッドを気にしなくてよくなったら、普及すると思うんだ
x巻子 o関数
追記(?) それを解消するためのアルゴリズlムであり、末尾再帰なんだと思う
プログラミング言語は道具に過ぎないってことを忘れてるだろ 現実を無視しちゃいかんよ
193のどこが間違えているのか教えてください
214 :
デフォルトの名無しさん :2011/11/22(火) 21:15:40.50
プログラマーか否かに関わらず、 人は手続型で思考する。 だから、先入観の無い子供でも 関数型は手続型より難しいと感じる。 S式や再帰を強調し、ほら簡単だろと言うから 関数型は嫌われてメジャーになれない。
手続き型が自然なのは同意だが 一方数学というのは思考を簡約できる道具なわけで 手続きに関数の表現を盛り込んでいくのがいいと思う
216 :
デフォルトの名無しさん :2011/11/22(火) 21:41:57.49
手続きが自然ってほんとかな? 疑問だな。
高校数学あんまやってないプログラマのこと考えたら自明だろ
むしろC的なメソッドを先にやってから 中?高?で関数を教えたほうがいいかもしれん
手続きが思考に近いってのには異論はない
末尾再帰がバッドノウハウてどういう意味?
今日考えていたんだが、 UMLで設計するんじゃなくて、DFDで設計したらいいんだよね?
状態がないのに自然なわけない
関数言語の簡単さ、綺麗さって オフサイドルールの面も大きいと思う
中括弧言語は それだけで下品になるからなぁ。
>>206 ポイントフリーは読みにくい型エラーの温床になるから
あんまりやらないようにしてるんだけど
でもHaskellって実際のコード見ると妙な演算子があちこちにいるよね <+>とか.|.とか>>=とか
ポイントフリーといえば、ほくろ付き巨乳とかあるね。 (.).(.)
>227 そうそう、だいたい奇天烈演算子大会になってるよね。 で、演算子の字面見ても殆どイメージ湧かないし。 いや、別に二項演算子が嫌いなわけじゃないけど、セルフドキュメント性が低すぎる。
>>214 でも、なぜか
x = x+1
等しくないよ?という入門者の意見の多いこと多いこと…
この段階では、関数型言語の方が自然らしい
でも、そこで躓く入門者というのを見たことがない。 都市伝説なのではないか。
>>227 Haskell使いの目指すところが手続的な個所も関数的に書こうとする事だからね…
そこが、ちょっと珠に傷って気はする
手続的に書く方が自然なところは手続的に書いて、関数的に書く方が自然なところは関数的に書けば良いのに、とは思うよ
関数的に書ける所では、デッドロックとか考える必要なくて、簡単に並列化できるし、手続的に書く方が自然なところは普通に手続的に書けるんだしさ
>>230 でも「三角形のこの頂点のx座標y座標は動かせないよ」と言っても
どうして?と言われるぞ…
>>231 居た
xとyの値を交換するってので、
temp = x
x=y
y=temp
ってするじゃない?
何でtempが必要なのか。いくら説明しても分からない奴がいた。
メモリの仕組みも習ってるはずなのに、理解できないらしい。
多分、メモリの仕組みそのものが理解できてない。
関数型言語の場合
タプルで受け取って、そのまま交換すればいい
swap (x,y) = (y,x)
これなら、そういうレベルの人でも分かるだろう。
・・・と、思いたいw
>>233 動かす(新しい座標を返す)関数作ればいいだけだろ
ハスケラが言う自然ってのはハスケルっぽく書けるということで、 それが日本語で普通に考えた時のやり方と全然違っていても あくまでハスケルっぽいほうが自然なんだよ。 同じように、ハスケラが言う関数プログラミング的というのは ハスケルっぽく書いてあるということで、MLとかLISPとかで スマートに書いてあっても、それは関数プログラミング的じゃないんだよ。
>>234 手続き型でもswapぐらい普通に実装できるが。
def swap(x,y):
return y, x
>>235 そんなので騙せるのは大人だけだよ。
新しい三角形をつくったって、元の三角形は動いてない。
>>236 日本語とか以前として、算数/数学っぽく書けるって感じかな
数学に国境はないから、日本とか外国とか関係ない
>>237 それを教えてない段階で疑問持たれる訳で
関数型言語は数学ベースだから、そう言う疑問を持たれにくいし、疑問への回答も論理的
(こう言う機能が有るよ!!ではない)
>>238 それが、後から元の三角形が必要になった時の利点
(手続き型だと新しい三角形を作る前に保存してないといけない)
>>240 教えてない?
あんたが知らないだけでしょw
関数型の人ってどこまでジコチューよww
>>241 それじゃ子供どころか大人も騙せないぞw
それで説明できたつもりでいるようだから、関数型はダメなんだよ
こういうスレにわざわざ議論しにくる人は、 叩く方も含めてほぼ100%関数型言語ユーザと思われ。 関数型言語の「メリット」は説明されなくても分かってるのでは。 Haskellでグラフのデータ構造を定義する上手い方法はあるのだろうか。 class Node { Set<Node> edges; ... }; 普通のオブ指手続き言語ならこれだけの話だが。
>>239 ハスケルじゃ関数名や変数名はつけないのか?
mapとかfoldとかfilterとかは世界共通の言葉なのか?
ハスケラのジコチューっぷりは世界共通なのか?
>>244 俺はハスケラじゃないんで分からんけど、それってHaskellじゃ難しいの?
データ構造の定義に手続き型とか関係なさそうだが……
>>246 edges への破壊的代入が出来ないとしたら?
Google Trendsで現実見て来いよ
Haskellでも破壊的代入はできるんだけどね。 デフォルトじゃできないだけで。
正直、記号の分かりにくさはどっちもどっちじゃないかな
>>230 っ PASCAL
っ COBOL
他にも手続き型で代入演算子が = でない言語はあったと思うぞ
>>234 それも最近の言語は x,y = y,x と書けたりするからなあ
>>234 分かるまで、ハノイの塔を実際にやらせてみるとか、どうだろうね。
多重代入サポートしてる言語でも y = x x = y と書いたらもちろん意図した結果にはならないので、なぜこう書いたらダメなのか というのはどのみち理解しないといけないような 変数と値のセマンティックスは値型/参照型云々でも違ってくるので 初心者にとってはそう簡単じゃないのでは エイリアシングからくる初心者にとっては不可思議な問題を とりあえず考えなくともよいという意味では、参照透明だと確かにわかりやすいのかも
多重代入サポートしてる言語で y = x x = y と書くのは例えばどんなとき? 僕分からないんで教えて下さい。
多重代入をサポートしてない言語なら、どんなときに書くか分かるのか???
二行目の x = y には何の意味も無いよね〜
>>245 え、そこから英語で躓くのかよ
変数や関数に対した英単語でないだろ
難しい話じゃなくて 関数を書くのは関数型言語の方が楽 手続きを書くのは手続き型言語の方が楽 ってだけじゃねーの?
デメリット側から言えば たかが map のために functor が必要になるのと たかが代入のために monad が必要になるのと 究極の選択。マシな方を選べ。ってだけじゃね?
で、具体的には?
個人的には。関数は第一級な方が当然便利。 参照透明性は要らん。言語に強制されるのは邪魔なだけ。
なので、純粋ではない関数型言語か closure を扱える手続き型言語がいいね。
ほうほう、君の中ではそうなんだね。よかったね。
で、君は?
で、君は?
ここで逃げるのが Haskell 厨
ほんとHaskell厨はクズだな
267 :
デフォルトの名無しさん :2011/11/23(水) 13:40:57.32
これは Haskell 厨のカスさがよく分かるスレですね
っていうか Haskell ってダッセーよな
Haskell はOSすら書けない糞言語
Hasmelって言語があるそうだな
1行 連続ポスト厨が現れるとスレの質が相当低下するからな。 もうこのスレもおしまいかも。もともとフレーマー用だから いいっか。
なるほど、Haskell 厨はそうやって逃げるわけね
もういいか? 参照透明性って、プログラマの責任で保証するというのでも 大した手間じゃないような気がするんだよな。 言語として副作用を持たないということは本当にメリットなのか? デメリットの方が大きい気がする。 純粋だってのは認めるが、それは数学的な美学の問題。 プログラマの利益にならなきゃプログラミング言語としては使えないだろ。
低下って 元々質()の低いスレで何言ってんだか いいっか。
もういいか? 参照透明性って、プログラマの責任で保証するというのでも 大した手間じゃないような気がするんだよな。 言語として副作用を持たないということは本当にメリットなのか? デメリットの方が大きい気がする。 純粋だってのは認めるが、それは数学的な美学の問題。 プログラマの利益にならなきゃプログラミング言語としては使えないだろ。
結論:Haskell はクズ
>>220 最適化をしようと思ったら、末尾再帰でないものでも無理にでも末尾再帰
のフォームに変換しないといけないけど、それは言語の文法上の話じゃなくて
コンパイラやインタプリタより下層の制約から来てる。そこからバッドノウハウ
臭さがある。そんな制約なしにどんな再帰でも最適化されるようなものだったら
末尾再帰にこだわらなくてもいいだろうしね。
多分、扁桃体から直接手を動かしてそうな人は関数型やってる ほとんどの人は相手にしないんだと思う。やっぱり情動の制御 できるように前頭葉を鍛えなきゃ。頑張ってリハビリしたほうがいいよ。
>>277 逆に考えるんだ。
そもそも call を jmp に置き換えるのが末尾再帰除去であり、
末尾再帰除去の中で call が自分自身を呼び出している場合がループなのだ。
つまり、手続き型言語の連中が当たり前のように使っている
ループという制御構造それ自体がバッドノウハウなのだ。
彼らはバッドノウハウだと思っていないようだが。
そうだね。
自動的に末尾再帰に変換して除去してくれるのが理想の最適化コンパイラ ーーーー壁ーーーー プログラマが末尾再帰に書けば除去してくれるのが関数型言語 ーーーー壁ーーーー 末尾再帰を除去できない変わりに破壊的代入とループ構文を導入して プログラマが手作業で末尾再帰除去できるようにしたのが手続き型言語
Haskell 使うくらいなら HSP 使うはww
それ随分と目的が違わねw
HSPは0行でウィンドウが出せる
>>280 おれも息を吐くが如く、末尾再帰にはお世話になってるけど、この話と
手続きのループとは話は別かな。
手続きのループに慣れ過ぎると、悪癖プログラマっぽいものしかいなくなる。
少なくともそれで関数をやるとね。せいぜいiterateにしてくれよと言いたく
なるけど、副作用の世界が絡んでるから一対一対応じゃない部分があるよね。
見た目も下品なループなんて抹殺すればいいが。藁
万能な Ruby が最強だということが分かった Haskell より速いし
あ、勘違いしてた。別ではなかったな。ごめん286取り下げとく
>>287 速い?
ghciは確かに遅いが、ghcでコンパイルした後だとLLじゃ話にならん速さだぞ?
OCAMLはコンテストでは強いらしいが 初心者ポンと出されて 一日でどこまで作れるようになるかコンテストがあったら 手続きのほうが強そう
どうだろう? 全くのプログラミング処女を捕まえて、教える場合と、クセのついたプログラマ が学ぶ場合と違ってくるからな。変なクセがある分関数童貞の手続きプログラマ のほうが、プログラミング処女より物分りが悪いってことはよくあるみたいだが。
OCamlは関数型だけど手続き型でもあるから 純粋指向の人達には軽く見られるけど、習得はし易い部類かと
IO Monadって結局は副作用をランタイムに押し付けて 言語レベルでは知らんぷりしてるだけじゃん。 「臭いものに蓋」で、副作用による依存性の問題に 正面から向き合ってないよね。
「ケンロン!ケンロン!」 「うわ、何アイツ、キモ・・・」 「ケンロン!ケンロン!」 「なんか臭いし・・・関わらないようにしようぜ」「そうね・・・」
ハスケラみたいな排外的で独善的な奴に仕事を任せたくないよね ハスケルで有名なプログラムって、グラディウスとかパールとか 既存のプログラムの書き直しばっかりじゃん
Haskell 厨 「我々は高度な理論に基づいてプログラミング言語を扱っている。実装重視の土方とは違うのだよwww」 「またあんなこと言ってるけど」 「いいよ、あいつにはリストの長さを求めるプログラム書かせとくからwww」 「そりゃ大仕事だなwwww」
>>293-294 教える経験のある人たちからはそうゆう話は時々出てくるくらい
だけど、違うと思うならそれでもいいよ。ずぶの素人より知ってるほうが
難しく感じるっていう話は、多少ショッキングだろうから。
しかしながら、この手のパターンはよくある話なんだよね。
ML系やSchemeが教育で使われる背景もあったけど、調べてくれ。
ほらね。結局逃げるんだよ。
>>302 それはプログラミングではなく計算理論も合わせて教える場合だろう。
>>300 それはどんな言語、どんなパラダイムでもそうなの。
ハスケルだけ特別、関数型だからみたいな事を言うから小馬鹿にされるの。
なんでこんな滑稽なことが起きるのか?という背景だけは触れておくか なまじっか知ってるために、自分の頭にある今までの学習パターンに当てはめる が実は、当てはめたら沼に入るパターンも多いからさ。 プログラミングで変なクセがついたら矯正しづらいってのもよく知られてる けどな。だいたい学習の王道は、副作用もできる関数型から始めるほうが、 いいからね。手続きから始めると、データ構造まで到達して使えるようになるのに 負担が大きいしね。
結局
>>302 の中で完結してるんだから、何言っても無駄だと思うよ。
>277 × 最適化をしようと思ったら、末尾再帰 ○ 実用的な大きさのデータを扱おうとしたら、要末尾再帰
>>305 誰がハスケルを取り上げてそんなことを書いた?
さすがに、これ見た時アホちゃう?と思ったよ。
でも関数型言語って、 少なくとも数学的帰納法をすんなり理解できるところまで教育を受けてないと無理でしょ。
>>306 さっきからその特徴的な改行はなんなの?
さすがに、これ見た時アホちゃう?と思ったよ。
>>310 高校生レベルならOKってことだね。それがわからんというのは
プログラミングするにしても、資材を並べるだけしかできないと思うよ。
論理的に考える素養がなさそうだからね。
>>309 いや、アホはおまえw
「初心者のほうが、かえって理解が早いことがある」なんてことは
構造化プログラミングの時にも、
アメリカの初等教育でLOGOが流行した時にも、
オブジェクト指向が普及しはじめた時にも、
同じことが言われていた。
関数型だからとか、もうアフォとしか言いようがない。
>>313 いや、普通にパソコン好きな少年なら、
高校生レベルになる前にとっくに「クセ」がついてるでしょ。という意味です。
「論理的に考える=関数型で考える」 完全にカルト信者だw
>>313 そういう気持ち悪い言い回しするから友達いなくなるんだよ。
ハスケラ発狂w
>>314 頭悪いな。違ったものをすでにみにつけてるものよりか何もないほうが
吸収が良いことがあるという事から、ずぶの素人とすでにやってる人が
学ぶのでは違う。と書いてるんだが。いい加減、わけのわからん早とちり
で勝手に都合よく解釈するのは。。。馬鹿な奴にアホと言われても
屁とも思わんよ。鼻で笑ってるだけだから。
くだらんやつ相手にするのも暇な時間だけにしなきゃ。
>>315 その仮定が適切なのか、ちょっとわからんし、一般的だとは思えないよね。
共通のコンセンサスがないというのだけはわかったが。
関数型厨の選民思想は見ていて爆笑なのだが、 ご本人達は本気で信じているのだということを思うと可哀想でならない。 カルトって怖いね。
さてはこいつ最近Haskell覚えた高校生だな。 中途半端に頭いいからはてなあたりででかい口叩いちゃう系の。
>>319 だから、一般論としてそういう話があるのは一向に構わないけど、
それと「素人は関数型の方がよい」という主張が繋がらないということでしょ
これはあえてキモい振る舞いでハスケラを演じることでイメージダウンを図るハスケルアンチとみた
素人に勧めるなら、まずはなでしこみたいに、識別子がほぼ全部日本語の関数型言語を 作ってからだな。
>>323 そ。関数型のところに「構造化言語」「LOGO」「LISP」「Java」どれでも当てはまる。
もっと一般化すると、
空手とかで他の道場で変なクセつけた中学生よりも、
はじめて空手を習う小学生のほうが教えやすい。
あたりまえだってw
Haskell厨はキモイなぁ
まあ、どっちから始めるのでも構わないけど最初にやる言語は重要だと思うよ。 逆に、整数型が当たり前のように多倍長な言語で入ってしまうと、 そういう事を気にしなければいけない言語に慣れるのは大変だと思う。 手続き型言語の中で言えば、ポインタやメモリ管理なども同じ問題。 Java→C と C→Java のどちらが「二番目の言語」を覚える障壁が低いのか。 関数型言語の方が、手続き型言語よりも高水準だね。より抽象度が高いという意味で。 そこはそうだと思う。 それ以外の話、使う人のレベルがどうとか、初学者にとってどうとか、そんなのは議論の余地大有り。
「10の階乗ってね、1*2*3*・・・*9*10ってやることなんだよ。」 これなら小学生でもわかる。 「10の階乗とはnの階乗ならn-1の階乗で、1の階乗や0の階乗なら1なんだよ。」 これを小学生が聞いたら「ハァ?」ってなる。
関数型言語全般はともかく、IO Monadは手続き型を知らない方が学び易いかもな 知ってたら絶対「なんでこんな面倒なこと覚える必要があるの?」 って気になって習得に集中できない メリットを聞いても「参照透過性がむにゃむにゃ……」みたいな説明しかしてくれないし
333 :
331 :2011/11/23(水) 18:23:18.61
書き間違えたorz 「10の階乗とはnの階乗ならn-1の階乗にnかけたもので、1の階乗や0の階乗なら1なんだよ。」
>>332 手続き型を知らないひとにはIO Monadをどう説明するの?
結局は参照透明性ムニャムニャになるでしょw
だって、それが本当の理由なんだから
ケンロン!ケンロン!
>>331 そう。それ実はかなり重要なところだと思う。
手続き型言語でも closure なんかは当たり前に取り込まれるけど、
map や filter といったところは、手続き型言語専門の人にとっても簡単。
fold をスッと納得できるかどうか。そこが壁だね。
>>334 知らなかったら疑問に思わないから、「面倒だな、でもそういうもんなのかな」
って学習するんじゃないかな
可哀想だけど
で、その学習しやすい関数型言語って、具体的にはどれのこと? まさかHaskellさんですか?
>>328 > 関数型言語の方が、手続き型言語よりも高水準だね。より抽象度が高いという意味で。
ぷ
お前が言う抽象度ってのはラムダ抽象だけだろw
世の中には他にも色々な抽象があるんだよ。
例えば、関数型言語は高階述語論理よりも抽象度が高いのか?
>>340 機械語としての0,1ビット列から、より遠くに離れている方が抽象度が高いという意味です。
なんでHaskell厨ってここまで上から目線になれるのかな
ハスケル使える俺ってスゲエ!って酔ってるからじゃないかな?
>>296 そもそもIOモナドの導入は、参照透明性を守りながら入出力をしたいという
言語の表層の問題を解決するために導入されたものであって、
「副作用による依存性」とか難しいことを解決しようとしてる訳じゃないから、その批判は的外れ
はてなの灘高生なみのキモさを感じる
reft x = 3; これでxはintとかに型推論して参照透過扱い、 というのはどう?
却下
めんどくせーから、お題出して、各言語で書いてみようず
全くのプログラミング処女を捕まえて、教える場合と、クセのついたプログラマ が学ぶ場合と違ってくるからな。変なクセがある分関数童貞の手続きプログラマ のほうが、プログラミング処女より物分りが悪いってことはよくあるみたいだが。
理論が美しい言語はHaskell以外に存在しないからね。 不勉強な君たちには理解できないと思うけど。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
発言をコピペしてそんなに楽しい? ... 幼稚すぎる。
>>351 逆はポール・グレアム始め多く関数型言語覚えてると手続き型言語でも良いプログラマになると聞くが、どっちが本当なんだぜ?
x多く o多くの優秀なプログラマが
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
>>358 理由は簡単なんだ、アルゴリズムを理解するのにschemeやML系というのは
すごく助けになる。特に木構造の理解には良いし。
だけど、手続き型というのは、文法ノイズが多いことでアルゴリズムを理解
するときに、混同したりということも起こりえるから。そんなこんなで、
データ構造を扱うのが気楽にできるというのもあって、扱う問題に対して
適切なデータ構造とアルゴリズムを選択できるという利点があるからだよ。
感覚的にわかってたら、C++のSTLだってJavaのCollectionだって扱う感覚
が分かるってことからだよ。
なんか真性のキチガイにストークされ始めたようなので、 退散する。キモいもん・・・・。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
ハスケラは逃げる口実を与えてくれたことに対して感謝するべきだなw
>>365 独善の極みだな
吐き気がする
おまえみたいのが関数型の普及を妨げていることに気付け
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
>>358 理由は簡単なんだ、アルゴリズムを理解するのにschemeやML系というのは
すごく助けになる。特に木構造の理解には良いし。
だけど、手続き型というのは、文法ノイズが多いことでアルゴリズムを理解
するときに、混同したりということも起こりえるから。そんなこんなで、
データ構造を扱うのが気楽にできるというのもあって、扱う問題に対して
適切なデータ構造とアルゴリズムを選択できるという利点があるからだよ。
感覚的にわかってたら、C++のSTLだってJavaのCollectionだって扱う感覚
が分かるってことからだよ。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんで発狂してんだ? OOPのVisitorパターンが冗長だって仄めかされたから?
仄めかすも何も自明すぎて
便乗荒らしじゃないか
Haskell で回答出てないので。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
>>244 >Haskellでグラフのデータ構造を定義する上手い方法はあるのだろうか。
これ悩むんだよね
前やった時はとりあえず計算量無視で関数を作ってみて
あとで速度が必要なところだけ定義は同じで内部でSTモナドを使った関数に置き換えた
木構造がシンプルに書けるといっても破壊的代入がないと
大規模なデータではシンプルなコードは実用的な速度が出ない
実用的な速度を出すには手続き型と同じような書き方を回りくどい方法でとらないといけない
あと大規模データを延々と処理し続けるようなプログラムだと
遅延評価は思いがけないところでメモリリークを起こしやすいように思う
そしてそれを見つけるのが困難
スクリプト的な使い方には非常によいと思う
でも、実用的にはOCamlくらいがいいんじゃないかな
HaskellはType Classや構文が羨ましいけどね
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
>>386 ん、若田
ただな。問題は、自分がプログラミングHaskell読み終わってない初心者なんだなw
使用例とか、どういう動きを期待されてるのか知らないと、書けんw
教えてくれw
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
>>393 あ、大丈夫
typeで独自の型を作るところまではやってるから、後は何とか出来ると思う
あの薄さの入門書でどこまで出来るかやってみたいんだ
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
なんか 呆れる連中が多いな。Haskell固有の話じゃないのにな。 勝手にHaskell厨と騒いでるのを見てて、ここは、アホの楽園なのかと・・・。 Haskellは純粋だけにOcamlとかと比べても堅物な言語だから、 その点が容易かどうか。最も、難しいところを置いといても プログラミングはできるけどね。 OOPとの対比になるけど、Visitorパターンが理解できたら、 無名関数でやってることと同じようなことがOOP言語ならできるけど OOPでVisitorパターンの位置づけはどうなのかだよ。逆に、 関数型やってる奴のほうが、使えるパターンかもしれんが。
グラフならペアのリストなりセットでいいような
アルゴリズム系でHaskellに挑むとか、無謀すぎだろ
>>398 そのグラフからエッジを一本削除してください
書けない言語で無理しなくていいよ
>>391 回りくどいって言うが、IORefはOCamlのrefとほとんど同じだよね
名前が長くて鬱陶しいのは認めるけど、実用性をうんぬんするような違いではないと思う
しかし自分が普段使ってない言語の実用性が低く見えるのはある程度仕方ないんだろうな
俺も「OCamlってマルチコア対応してないのにどうやって実用プログラム書けるんだろう」とか思うし
>>403 いや、グラフとか、エッジを削除とかの用語が分からんだけ
マージソートも、コードなしのアルゴリズムの本で組めたから
(「アルゴリズムのキホン」とか言う、これで手続型言語で組めるのかいな?という舐めきった本)
分からんなら黙ってればいいのに
>>404 いや、それは関数型特有の独善性だから。
勝手に一般化しないでくれ。迷惑だ。
むしろHaskell勉強しててグラフ理論も知らんとかバランスが悪い
もち、手続型の人たちも、グラフの定義とエッジ削除のコードの準備お願いしますね
>>407 関数型の独善性って?関数型ユーザの独善性って言いたいの?
それこそ不用意な一般化だろ。同意できないならそうとだけ言えばいい
だから出てこなくていいってば。pyths のコードで「素数って何か知らんけど教えて」といわれてるようなもんだ
pyths関係なかった。あれはピタゴラス数か
グラフを知らないのにどうやってハスケルの動作原理を理解したんだwww
>>413 え、Pythsはピタゴラス数であって素数じゃないけど・・・・
手続型の人が怖がってるんですか?
初心者Haskellerに?
>>412 バーカ、おまえが先に一般化をしたんだろ
他人の一般化を批判する権利はない
自分だけが特別だと思ってる関数型厨の典型だな
>>415 え、グラフ理論(?)とHaskellの動作原理に何の関係が…
と、言うか、動作原理は理解してない。・・・と思ってる
>>417 なにそれ。互いのミスを指摘しあうのは議論なら当然だろ
「お前が先に間違えたから俺の勝ちな」とか言っても始まらんよ
あと何か一般化が無条件で悪いと思ってる?
>>404 >回りくどいって言うが、IORefはOCamlのrefとほとんど同じだよね
型がクドくなる
関数型言語のクイックソートって空間計算量が O(nlogn) という理解で正しい?
あとSTモナドは型注釈必須なのでめんどくさいから使いたくない まぁunsafeなんちゃらつかえばいいんだけど
>>421 使った端から到達不能になるから
O(n)でいいんじゃない?
>>421 Haskellの有名なやつを念頭に置いてる?
あれは遅延リストだから空間計算量は訳分からんことになる
最悪O(n log n)かもしれない
同じことを正格なリストか配列でやればO(n)
in-placeのクイックソートを実装すればもちろん追加メモリは定数で済む
あの・・・ グラフの説明とエッジ削除の説明は・・・
いや最悪O(n^2)っぽい
>>425 まともなデータ構造の教科書を買うか借りるかぐぐる
ocamlerがHaskellをディスるスレ
実際ocamlは使い易いし
グラフに 4種類のノルムを定義して それぞれについてダイクストラ 結果に応じて条件分岐して 各エッジに容量を設定して 最大フロー問題
ち、自分で出来ない事を関数型言語は〜とか言わないで欲しいなぁ… 関数型言語の検証ができないじゃないか 自分は文法に惚れただけで、実用可能かどうかははっきりしてないんよ このスレが検証にうってつけだと思ったんだけどな・・・
Haskellの前は何使ってたんだ?その言語が手続き型なら自分で書けよ。 要はグラフ理論知らないだけだろ?勉強不足。
>>432 ハスケルではつらそうな例を考えて見ました
>>432 いやだから・・・
マジ初心者だから、ダイクストラから分からんのよ…
一応、ググったらCのコード出てきて、typeすら使う必要ないっぽいけど・・・
ダイクストラ法 Haskellでググったらこんなん出てきてるけど
type Index = (Int, Int)
data Node = Node { cost :: !Int, pos :: !Index, from :: !Index }
deriving (Show, Eq, Ord)
ソース
http://haskell.g.hatena.ne.jp/route150/20100502/1272792417 こういうのを、自分はちゃんと自分で書きたいんだよ
んで、手続型言語のソースが一向に出ないのも、説明が出ないのも何でよ・・・
手続きの書き方は自明すぎるから
面倒くせえからグラフ知らないなら双方向リストでいいよ。それがグラフだ。
>>434 そうよ
手続型だろうが、関数がら多だろうが、それを知らなきゃ書けんのよ
マージソートのときは、Haskellでは分かっても、手続型言語で書き方分からんかった(いや、配列じゃなくてリストで作れってなら、今なら作れるけどさ)
色々やったよ
CもRubyもJavaもSmalltalkまでやったさ
>>437 なら、それがHaskellで書くヒントになるから書いてほしい
>>439 「グラフというデータ構造を知らないんだから書けるわけないだろ、教えてくれないそっちが悪い」ってか?
それお花畑すぎねえか?
>>440 だから双方向リストでいいって。
末尾に O(1) で要素を add できる。
末尾要素を O(1) で remove できる。
末尾要素を O(1) で取得できる。
一つ前の要素を O(1) で辿れる。
これを満たすデータ構造を作れ。
>>443 グラフ知らない人に
オーダー記法使って話しかけるなww
すまんかったwww
てかオーダー気にしないならある意味Haskell最強かもしれんwww 代入なんて効率のためにあるようなもんだし
>>443 ふむ、ちょい頑張ってみる
酔っぱらってきてるから、明日とか明後日になるかもだけど、作ってみるよ
逃げるか。俺も泥酔した状態で443書いたんだけどな。
>>446 うい、無限のメモリと無限のクロックがあれば最強
だから、個人的には64ビットOSの普及がHaskell普及のカギかな?とか思ってみたり
CからC++、さらにLLへと流れてきた延長で
おいおい64ビットOSの普及がカギとか...
>>448 いや、書くよ
今日書けるか自信がないだけ
何つーても初心者(少なくともHaskellはw)な上に、酒がまわってきた
>CもRubyもJavaもSmalltalkまでやったさ という人が双方向リストを作るのに明日か明後日になる。 それがHaskell
>>450 ぶっちゃけ、コード書くのは楽だけど、LLとはどっこいどっこいだとして、やっぱメモリ食うもんよ
クロックの方は、腐ってもコンパイラだから、LLより速いんだけど(Rubyの後でHaskellやってたから、マジビビった)
>>452 いや・・・
入門書で挫折してるから…
覚えた言語の数が問題じゃないんですぜ?
>>453 それで、32ビットOSが64ビットOSになるのに合わせて、搭載されるメモリが2^32倍になるのかな?
一方ジャバラーはライブラリをそのまま使った
>>443 あ、ついでだけど、双方向リストって英語でなんて書くの?
関数名&ファイル名にしたいんだけど
>>456 そりゃそうだろ。ソースを見て写経してもいいが意味ないし
Haskell勉強しようって奴はこんなのばかりなのか?
実のところocamlerだがhaskellに偏見を持ちそうだ。
あんたら話しをごっちゃにしすぎ。一次資料に当たれ。
>>455 実用的にはそこまで要らないだろうけど、末尾再帰使わんと、4GBじゃ不足する場面もあるんよね…
末尾再帰よりはループの方が素直なんよ
(そういえば、Haskellにもfor関数あるっポイんだが、使い方分からん…。副作用のある関数で使うモナドの糖衣構文do内の引数なし再帰は実質、ラベル付きGotoだから、困るわけではないんだけど…)
自分でfor関数作った方が速いんじゃろか…
(doが付く関数内でしか使わんけど)
圏論の勉強中だから静かにしてくれる?
>>459 たぶん…
かなり稀な方だと自覚してる
ウザがられるの分かってるけど、Haskellが一番しっくり来たんで絶賛宣伝中
逆効果かも知れんけど、その時は、真のHaskellerが何とかしてくれると(ry
>>464 名前欄にHaskellSamuraiとか入れとくといいよ
Haskell侍。。。Ocaml岡村。。。。
はすけるのコードって、どうやってパフォーマンスチューニングするん? メモリ足りない時とかI/Oの帯域幅が重要な時とか。
アルゴリズムの見直しは大きいだろうよ。okazakiを参考にするとか
一応、双方向リストっぽいのは出来たんだけど、自信がない… data DList f l = Null | DList f l deriving (Eq, Ord, Show, Read) そもそも、双方向リストってのが、どういう動きするのかが分からんのだもん・・・ 一応、自分の作った双方向リスト(か分からない何か)の使用例 >Null Null >DList Null Null DList Null Null >DList 1 (DList 2 Null) DList 1 (DList 2 Null) >DList (DList Null 2) 1 DList (DList Null 2) 1
上から順に、 空リスト 空リストの空リスト 通常のリストと同じ方向にリスト作成 通常のリストと逆方向にリスト作成 これを使ってO(1)で結果が返るadd関数やremove関数作を作れるかはまだ分からない状態
セルに前方と後方へのポインタ2つをつけたらいい。 それを使ってrmapとかrconsとか実装してみればいい。
>>315 懐かしいなあ、俺とかプログラミング始めたの小学生のときだわ
初めての言語はBASICだったが
仮に初めてが関数型言語だったとしたら、さんすうの知識でやれたんだろか?
>>419 なるほど、ハスケラってメンヘラなんだな
>>472 双方向リストモドキを定義しなおし、そのhead関数も定義してみた
data DList a = Null | DList (DList a) a (DList a)
deriving (Eq, Ord, Show, Read)
dhead (DList Null x _) = x
dhead (DList xs _ _) = dhead xs
使用例
*Main> dhead (DList (DList Null 2 Null) 1 (DList Null 3 Null))
2
>>404 > OCamlってマルチコア対応してないのにどうやって実用プログラム書けるんだろう
Unix.fork または ocamlmpi
マルチスレッドもいけるF#最強ってことですね
f# はfuntor ない
>>476 それ、2分木だろ
全然双方向リストになってねえよ
>>476 流れは良くわからんが
そも双方向リストは単純に再帰定義できないからhaskellでは素直に書けないよ
双方向リストを実装したライブラリというのも、俺は見たことないな
どうしても使いたいなら頭を捻るか、STモナドやIOモナドに入れて対応しよう
再帰定義できないデータ型としては例えば他に両端キューやハッシュテーブルがあるけど、
haskellの両端キューは特別な木で実装されてるし(前者)、
haskellのハッシュテーブルはIOモナドの中でしか使えない。(後者)
そして普通はハッシュテーブル使うぐらいなら再帰定義可能な平衡二分探索木を使うようだね
haskellのやり方というのはそういうものだ
>>481 分かりやすく二行でまとめると、
・手続き型言語やLisp/ML等の大半の関数型言語 --> 双方向リストやハッシュが「自然に書ける」
・Haskell --> 再帰定義やモナドといった「面倒な手法を駆使しなければ」表現できない
ということですかな
>>482 他の関数型言語がそれらを自然に書けるかどうかは不勉強なんで良くわからんな
ただ、双方向リストで必要な参照型と、ハッシュテーブルで必要な破壊的代入は、どっちもhaskellが生理的に嫌ってる部分だからね
その両方を簡単に扱える言語であればどちらも自然に書けるはずだよ
モナドはともかく、再帰定義が『面倒な手法』というのは手続き的な発想だな
むしろhaskellは再帰を愛しているからこそ、できる限りそれだけで対応したがる、というのが正しい
あんまり変わらない? うん、まあ、そうかもしれんね
手続き型が自然は疑問だよ、読み書きそろばんを小学校のうちに矯正させられ
るんだから。
小学校に上がる2年前にタッチタイピング、1年前にLISPで数の概念を教えて
中学卒業前に偏微分まで独学させたらおもしろい子供になると思う。学校では
数学を習うから手続き型も覚えるし、かなりちょうど良いんじゃないかな。
あと小学校で習う筆算の+−×÷の記法って特殊だよね。あとそろばん習って
いる人は今は少ないかもしれないけど、そろばん流暗算も特殊だよね。
余談だけど子供には読み書きもしっかりやらせたいと思っている。とくに書きは
意識的にやらせないと覚えないので意識的にやらせる。プログラミングの習得って
早ければ早いほどプログラミング歴が長くなって、時間感覚が豊富になるよね。
15歳からプログラミングを始めて18歳で考えるプログラミングや世間に対する
とらえ方と6歳からプログラミングを始めて18歳で考えるプログラミングや世間に
対するとらえ方はまったく違うものになるだろうね。15歳から始めたヤツは27歳
ぐらい必要だろうし。早くても24歳ぐらいは必要だろうなあ。これは読みと書きにも
言えること。数学はそういう時間感覚があるのか、知らん。
>>230 x = x+1ってx <== x+1の省略記述だよね、厳密には。教育言語のPascalがx := x+1なん
だっけ?
>>231 躓きはしないけど「うん?」とはなっていたなあ。
>>232 慣用句だと思って暗記して使うしかないけどなあ。9.9割はパターン認知処理で問題が
起きないので忘却曲線を意識してすべて暗記すればいいと偉い先生が言っていたよ。
>>236 日本語の算術的に考え方で言うとそろばんと升とかの方が歴史は長いんじゃないの?
近代化のために江戸時代的なものを脱ぎ捨てて今があるけど。
>>484 日本の教育システムは、採点し易いか否かを優先してるから、論理性は教える方も解ってないからなあ。
>>314 アメリカの教育って今の日本の教育並にウンコだっただけでしょ。
あとプログラミングの教育って相当難しいんじゃないかな。おまえら、
中高でかなり時間割り当てられているはずだけど、古文、漢文自作できるか?
あとA4二枚の英作文できるか?
>>321 選民思想なのかわからないが、人が選択肢している時点で合理的な判断をして
いるから合理性は出てくるだろうなあ。
>>331 それただ教えてもらっていないだけでしょ。今の数学の教科書みたいに二段飛び、
三段飛び当たり前だときついけど、小中高のすべて合わせて1,500ページの教科書を
渡して中1まで進めれば勝手に独学して進めるヤツは結構いると思うよ。
>>338 あいさつの概念、作文の概念、読書の概念、算数の概念、活版印刷の概念とか一々
やったら子供は逃げ出すだろうなあ。空手や柔道みたいに型を教えて、何年後かに
分かればいいだけ。
>>474 数学が得意で国語が不得意だったけどベーマガのBasicコードを写しているだけだったな。
付属のリファレンスを読んでみたけど、関数?(学校で習った関数だよな?)?だった。
市の図書館に行っても小難しい本しかないし、ネットもなかったらフリーソフトを
手に入れる手段もなかった。万単位のお金を払ってプログラミング言語を買う概念なんて
なかったし、そのソフトを仮に大奮発で買うとテキストを買うのは無理だからなあ。
やっぱり本でどうやって引き込んでいくかが大事な気がする。プチゲーム(ジャンケン
ゲーム等)を組ませつつ、数理的な問題も組ませつつ引き込んで行く。
80年代がマイコン全盛なんだっけ?子供向け本も多かったんだろうけど、今はそうい
うのが少ないんだろうなあ。子供向けではないけど個人のWebページで言語入門みたい
なのがあるからそういうのでアナルファックの味とか覚えるのかな。
>>485 論理性も教えるためにゆとり教育ができたんだけどね。小学校は熱心だったようだけど、
中高は一部の先生がボイコットしちゃったたみたいだね。まあ、ゆとり以前に
週5授業とか、予算と教員に教材仕込む時間を設けなかったりとか、色々と問題があった
し、ゆとり導入前にマスゴミが学校をガンガン叩いて劇場化して、教員が教えられない
状況を作っちゃったからどうしょうもないんだけどね。子供に一番良くないのは親が
教員を疑うことと教員が自信を持って教えられる環境がなくなることらしい。
アメリカのデータだとインディアン部族の教育が体罰あるらしいが、体罰したからって
変な子供になるわけではないらしい。文明先進民族の白人が勝手に「体罰は良くない」と
注意し始めて、インディアン自身が白人が言っていることの方が正しいと思ってしまって、
教え方にブレが生じて、荒れ始めたらしい。日本は家庭体罰に行政介入できるようになっ
ちゃったから家庭教育しづらいわ。子供の人権を盾にやりたい放題させるのは子供自身にも
本当に良くないと思うわ。まあ、この流れは当分止まらないんだろうけどなあ。
あと思ったけど手続き型言語の代表言語をいくつか出さないか? Cであったり、Javaであったり、.netであったり、Perlであったり、Pythonであったり、 RubyであったりだとCの実行速度を持ちつつ、VM上で動くのでOSを環境依存もなく、 Windows対応もよく、文書整形向きでワンライナーもしやすく、可読性もよく、日本人が 作った最強言語と錯覚させる恐れがある。個人戦でVSで戦ったら実際の所はどうなんだろ。 トーナメントつくって議論して勝敗決めていこうか。
ここはOcamlerがHaskellerを煽るスレでな
Haskellは純粋ゆえに、どうしょうもなく使えないパターンってあるからね。 双方向はそう幽霊だよね。学習用と見たときな明確に欠点かなと思ってる。 スペシャリストとジェネラリストに分けたら、Haskellはスペシャリストなん だよ。Ocamlはまだジェネラリストの顔を持ってる。 手続きが書きやすいかどうかは知らないけど、lispで構造体を使って双方向 リストを作ってみたら、いささかCと変わらん感じがする部分は出てくるよ。 どうしてもポインタ操作で破壊的操作が必要だからね。木構造はHaskellは 大変扱いやすいんだけどなぁ。HaskellというよりML系はというほうが適切か。 だから、木構造を上手に活用する方法を考えだすんだろうね。 HaskellでSICPの後継が欲しいってのもSICPスレで読んだけど、Haskellじゃ どうしても途方もなくめんどくさくなる章があるんだよな。それがHaskell の限界だと思ってるよ。限界を超えようとして頑張ってる人たちも多いけど 大変だよね。その頑張ってる人たちがいるから並行処理に魅力があるんだけ どな。
IORefやIOUArrayがりがり書き換えまで含めてHaskellだと思ってる
誰もHaskellで双方向リスト書かないの?
ocaml の特有の基本仕様は大体覚えたんだけど こっからhaskell 覚えてメリットある?
どうしてO(1)のハッシュマップを使わずに O(log(N))の平衡木を使わなけゃならんの? どうして双方向リストを使わずに 単方向リストや配列を使わなけゃならんの?
>>495 べつにハッシュマップや双方向リストを使いたければ使えば良いよ
そのかわりpersistentなデータ構造にはならないってだけ
>>496 効率の良いデータ構造をモナドの外で使えないのは不便じゃないの?
不便なこともあるね
ノイマン型コンピュータ、もっといえばチューリングマシン自体が手続き型なんだから、 その上で動かす関数型言語がぎこちないのは当然の理屈だな。
手続き型、関数型の概念は共に構造化がベースだから、チューリングマシンとは別カテゴリ。
>>495 そのためにありとあらゆる工夫をして高速化してるのがOkazakiじゃなかったっけ?
良く言えばすごいけど、Okazaki本は話しか聞いてないから見てないけど、SMLで
かかれてるんだよな?
悪く言えば、純粋のためのバッドノウハウと取られかねない。藁
Oderskyに空目した
それscala病 :-)
>>500 んなこたーない。
主流CPUの機械語が全て手続き型なのは紛れもない事実
>>499 ,500,504
用語がおかしいから意見が食い違う。
機械語は手続き型というより、命令型プログラミングという表現が正しい。
ハスケルの人達はLISPを馬鹿にしているけど 結局ハスケルの代数データ型は LISPのcar,cdrのリスト構造の範疇内でしか データを操作できないってことでOK?
>>480 こんなのも書いてみたけど、双方向リストじゃ・・・ないよね・・・
ジグザグな構造になっちゃうし
data DList a = Null | Prev (DList a) a | Next a (DList a)
deriving (Eq, Ord, Show, Read)
使用例
Prev (Prev Null 1) 2
>Prev (Prev Null 1) 2
Next 1 (Next 2 Null)
>Next 1 (Next 2 Null)
Prev (Prev (Next 3 Null)) 1) 2
>Prev (Prev (Next 3 Null)) 1) 2
うーん・・・
双方向リストの使用例みたいなのが見たい・・・
双方向リストは定義し難いが無限リストは定義し易い
じゃあ双方向無限リストでいいよ。
と、いうか俺の
>>481 の表現はまずかったな。すまない
『双方向リスト』は再帰定義できないから、
haskellは両端キューを『フィンガーツリー』で実装している
『ハッシュテーブル』は再帰定義できないから、
haskellは連想配列を『平衡二分木』で実装している
というのが正しい
Haskellはデータサイズが大きくなるとlogNだかの呪いがかかって使い物にならないってこと? この後どうなっちゃうの?
ハッシュテーブルのO(1)はメモリ効率の悪さとトレード・オフで実現されてるものだからねえ・・・ 連想配列として常にハッシュテーブルが最適とは限らない なにより一応両方使えるんだから適宜使い分ければよいでしょう
>>507 バカにしてるだろうかね?謎だな。エバンジェリストのところのhaskellの
wikiがgaucheのなのに。
木の上を行ったり来たりできるよってことでいいのか 確かに双方向だな
>>513 フィンガーツリーや平衡二分木というのはデータ構造に関する
汎用的なアルゴリズムだから、Haskell固有の概念ではない
実際、二分木による連想配列の実装は手続き型言語でも使われる
これに沿って
>>482 を書き直すと、
Lisp/ML等の大半の関数型言語 -->
・手続き型言語の経験者であれば、(破壊的代入を用いる事で)
その経験を活かして容易く双方向リストやハッシュを実装できる
・もしも参照透明性が必要であれば、(難解ではあるが)
フィンガーツリーや平衡二分木といったアルゴリズムで実装する事もできる
・どちらを選ぶかはプログラマの判断であり、
処理系からプログラマには「自由」が与えられる
Haskell限定 -->
・双方向リストやハッシュはフィンガーツリーや平衡二分木といった
(難解な)アルゴリズムを用いなければ実装できない
・プログラマは参照透明性の保証を、常に処理系から「強要」される
ということですかな
Haskellだと参照透明性が「必ず」保証される MLとかは参照透明性は必要であればプログラマが保証する必要がある と思いきやUnsafeIOとかあるしな
俺はunsafe系は流石に触らないなぁ・・・ といいつつtraceは使うんだけどね
Haskellの場合はプログラマが必要に応じて参照透過性を壊せる。
だからHaskellなら参照透明性を守ったまま破壊的代入ができるんだって もちろん破壊的代入をしないスタイルの利点(persistentなデータ構造、 状態に関するバグに悩まされない)は失われるけど、それは当然のトレードオフ
IOモナドに参照透過性があるって事?
>>522 X: Haskellだと参照透明性が「必ず」保証される
O: Haskellだと参照透明性をプログラマが「必ず」保証しなければならない
X: MLとかは参照透明性は必要であればプログラマが保証する必要がある
O: MLとかはプログラマは参照透明性を保証することもできるし、
保証しないコードも書けるという「自由」がある
>>526 うん。もうちょっと正確に言うと、IOモナドやらIORefやらを使うだけでは
Haskellの参照透過性を壊すことはできない
unsafePerformIOその他の危険な関数を使えば壊せる
ML系って参照透明性のことでschemeみたいに、!の有り無しで見た目区別する みたいな工夫をしてるの?よくしらんねんけど
>>525 >だからHaskellなら参照透明性を守ったまま破壊的代入ができるんだって
それは「モナドを使えば....」という前提があるわけで、
そのモナドで包んだ範囲内では参照透明性が保証されるという話だろ?
言い換えると、Haskell処理形は参照透明性が保証されたコードしか受け付けないから、
プログラマが(モナドを使って)保証したコードを書いているという事だ
つまり、
Haskell限定 -->
・I/Oや破壊的代入といった参照透明性を阻害する処理については、
すべてモナドを使わなければコードが書けない
Lisp/ML等の大半の関数型言語 -->
・モナドのような難解な概念を持ち出さなくても、自然にコードが書ける
・もちろん
>>136 のSMLの実例あるように、参照透明性を保証したコードも書ける
ということを意味している
手続き型言語およびLisp/ML等の大半の関数型言語に慣れた、いわゆる普通のプログラマにとって
たかが入出力ですらいちいちIOモナドを使わなければコードが書けないダメ言語が Haskell
まるでIOモナドが魔物ででもあるかのような口ぶりだな
>>531 たとえば「読んで; 計算して; 書く」という単純な処理は、
SMLなら以下のような明解なコードになる
(他のML族やLisp族でも同様なコードになる)
let
val x = 読む
val y = 計算 x
in
書く y
end
それがHaskellでは、こんな初歩のプログラミングですら
IOモナドを使わなければコードが書けないだぜ
どこをどう考えても 「Haskellはダメ言語」 だろ
>>530 単にdo書くだけなのに、そんなに手間か?
個人的には手続モードと関数モードを行ったり来たりする感覚
一次資料に当たれって。
>>533 他人様の作ったモナドを利用するだけの「末端プログラマ」であれば、
それでもいいんじゃね?
「読んで; 計算して; 書く」というだけの簡単な処理をするだけのために 「副作用」とかいう謎の概念を駆使しないといけない言語と比較するなら、 五十歩百歩だろ
副作用という概念は手続き型言語だけしか使わなくても知っておくべきだと思うが
>>535 入力して計算して出力するだけなら、それで十分じゃね?
何を無駄にモナド作るんだよ
>>537 そりゃ、アセンブリ以外の手続き型言語は大抵副作用という概念を持っているからな
>>532 Haskellはよく知らんがこんな感じだろ?似たようなもんじゃね
do
x <- 読む
書く y
where
y = 計算 x
>「副作用」とかいう謎の概念を駆使しないといけない言語 って手続き型言語のこと言ってるんじゃない?
>>540 細かいことを言うとそのwhereはletにしないとxがスコープにないのでエラーになる
do
x <- 読む
let y = 計算 x
書く y
ますます似てる
似てるどころか一緒じゃね?
まあアンチスレらしく不便な点を挙げるとしたら、 純粋関数として定義したものの、あとからその『内部』でIOを扱いたくなった場合、 printfデバッグみたいにここに一行挟んでー、みたいな気楽な使い方は、残念ながら出来ない。 一度IOを持ち込むとsafeなやり方ではその中から出られなくなってしまうから(つまり、関数の返り値の型が変わってしまう)
それはあるね printfデバッグに限ってはDebug.Traceを使うけど
>>514 いや・・・
自分が無理に副作用無しの双方向リスト作ろうと奮闘してグダグダにしてるだけ・・・
今月の数学セミナーによると、計算機科学全般の副作用を数学上で再現するためにモナドが生まれたっぽい
つまり、関数型言語のみならず、手続型言語全般の動作を数学上で再現するにはモナドが必要らしい
そういう意味では、モナドでオブジェクト指向も再現できるのかも
そういう意味で、モナドは副作用のない数学の世界に、副作用を再現する概念なんだよね
Haskellのモナドも、良く分からんが、そういう事なんじゃないかと思う
それはともかく、自分は双方向リストはじめ、勉強不足すぎるから、しばらくROMるよ
HaskellSamuraiさんHaskellスレにおいでよ。
関数型言語を使う予定はないが その考え方はいただいてやったぜ。 C++のSTLとかも影響受けてるんだよね?
数年すればお互い色々整理されて使いやすくなるだろう
そう思って既に15年 orz
まあ代入のある関数型言語は全部手続き型言語の影響を受けてると言っていい
Fortranの影響を受けてない高級言語など存在しない
お互いじゃなくて、Haskellの個性の沿った使い方を丁寧に教える 状況というやつじゃない?You learn a Haskell ...の最後になんで Zipperなのかがよく分かる流れだったよ。
結局のところ、lazy evaluation と eager evaluation の どっちがデフォルトが嬉しい?って話に尽きるのでは eagerな言語では、Haskellとは逆に遅延評価したい処理をモナドに包んだりするわけでさ まあ、普通のプログラマである俺にはlazyがデフォルトは厳しいわ
>>547 レベル高すぎて中々書き込めないけど、たまに書き込んでますよ
何ヶ月か前に数学セミナーで圏論の連載が始まるって書いたのも私だったり
(今月号で5回目だから、だいぶ前か)
for Great Goodって、どこのカルトかと・・・
>>555 >どっちがデフォルトが嬉しい?って話に尽きるのでは
いや、それはHaskellの特徴のほんの一部じゃないか
遅延評価よりも重要なものがいくらでもあると思う
型クラス、純粋さ、インデント構文、マクロとか
インデント構文が重要?
Haskellに遅延評価がなかったら、で誰か思考実験してみて
俺は重要だと思ってるけど異論もあるだろうな 具体的には、閉じ括弧を書かなくて良い場面が多いので、 関数の最後の引数にdoやラムダ式を書いたり、 激しくネストした関数呼び出しを書いたりしても見難くなりにくい これはコーディングスタイルにかなり影響を与えてると思う 閉じ括弧が少なくなるのはインデント構文だけじゃなくて $の影響もあるけど
>>559 横レスだが、個人的には見やすいので助かってる。
プログラミング始めた頃は、これパースしにくいだろ
センス無いなーと思ってたけど、使って行くうちに
インデント以外の事(データ構造とか)で頭を悩ます
ようになったんで、パット見判るのが良い。
>>559 読みやすくなる。あれだけ括弧のことを言われるlispでも実は
インデントでソースを読んでいるくらい。
>>564 つまりハスケルの開発もすぐ止まっちゃうの?
>>563 インデント構文は忘れた頃にコードに手を入れようとするとひどい目に合う
haskellでも文脈自由構文使う
インデント構文以外選べないpythonは使わない
そして 「あいつのコード読みにくい。どうしてインデント構文つかわねえんだ」 と陰口叩かれる
>>566 Haskellの場合、関数型言語特有の技術の有効性を検証する目的で作られた一面もあるから、まず開発が止まることはない
>>567 どっちかと言うと、忘れたころに読み直す時にこそ、インデント構文の方が読み直しやすいと思うんだが、痛い目って、手直しでインデントがズレまくるとか?
単に関数にまとめるのが下手なだけちゃうんかと
>>560 でかいファイルの読み込みでしょっぱな困る
コード上は無限リストで一気に全部読み込んでるように見えて、遅延評価で必要になった分ずつ読み込んでいくからメモリがパンクしないのに、遅延評価が無かったら、プログラマの方でメモリがパンクしないように気をつかわにゃならん
572 :
デフォルトの名無しさん :2011/11/28(月) 00:30:59.17
そんでも上手いこと要らないデータは捨てないと同じことだがね
573 :
532 :2011/11/28(月) 01:07:30.76
>>540 ,542,543
しばらく待ってみたが、残念な解答ばかりだな
>>532 では明確に書いていなかったけど、もしも「お題」を書くとしたら、
モナドを使わずに「読んで; 計算して; 書く」という処理をHaskellで書きなさい
ここで、ごく単純な逐次処理なのだから、再帰の使用は禁止します
というものになる。後だし条件かもしれないが、それくらいは推測できるだろ?
>>532 では「(Haskellじゃ)IOモナドを使わなければコードが書けない」と書いてあるんだから
Haskellのdo記法や>==はモナド向けの構文糖だ
お前等はそんなことも知らないナンチャッテ・ハスケラなのか?
Haskellという言語の表層だけで満足して酔っているお前等は「ドカタ・ハスケラ」だ
関数型でdo構文みるのは苦痛だな。見苦しいというのか、出来る限り避けたいよね。
(>==)の結合性を教えていただきたいものだなwwww
>>569 そりゃcleanも同じだ
Haskellだけ特別だと思ってる?
>>571 正格なHaskellなら間違いなくiteratee使うだろ
>>573 >モナドを使わずに「読んで; 計算して; 書く」という処理をHaskellで書きなさい
「モナドを使わずに」なんて妙な条件を読み取れって方が無茶だろw
もともと
>SMLなら以下のような明解なコードになる
と書いてあったから、モナドを使って同様に明快なコードになることを示しただけ
>>574 Haskellのdoならすごく読み易くない?
(>>=)やラムダを多用したコードの方が汚く見える
Haskellに限らず逐次実行のための仕組み一般(OCamlの;とかも)を指しているなら、
それなしでどうやってプログラム書くのか
do記法の中に(>>=)を混ぜるのが最強 異論は認める
581 :
デフォルトの名無しさん :2011/11/28(月) 09:18:03.28
>>573 >==が>>=のタイポだとしてもお前話にならないから帰っていいよ。
煽るにも技術的なバックグラウンドが必要だな。
>>578 そもそも「読んで計算して書く」って、それ自体が手順だしな…
手続き的に書くほうが自然だし、ちゃんと要所でそれが出来るのがHaskellなんだし
アンチの質が低すぎてアンチスレがアンチスレになっていない件
585 :
デフォルトの名無しさん :2011/11/28(月) 13:14:13.04
Haskellの長所でありクソな点は、計算の中に副作用を入れるのがモナドをやりくりしないといけなくてめんどくさいことですし。 副作用のある手続きの中に計算を入れるのは他の言語と大差ない。
>>579 どうしても避けられないところはあるけど、極力避けてるよ。
doの中ってやっぱり手続き臭が強くって、あのクサさは最悪だと感じてるから。
まるで卵の腐った匂いだ。
硫黄大好き
>>583 は結局、手続き的な記述の利点を認めているわけで、
だったら手続き型ベース+関数型スタイルでいいだろうとなる。
にもかかわらず関数型マンセーなのは矛盾を感じるな。
>>586 のハスケル原理主義のほうがかえって好感が持てる。
>>1 はScalaやF#なんが含めて煽りたかったんだろうが、
まさかHaskeller対その他になるとはな。
>>588 HaskellもMLも十分、手続き型言語とのハイブリッドだよ
逐次実行、破壊的代入、複雑な入出力、どれも避けて通れないアプリは多いんだから、
これらをうまく書けないような言語は汎用言語として欠陥がある
>だったら手続き型ベース+関数型スタイルでいいだろうとなる。
それよりも関数型ベース+手続きスタイルが良いと思ってる奴がHaskellとかMLを使ってるだけ
>>588 手続き型「にも」利点があるし、そのほうが書きやすく直感的な処理もある
自分は、 できるだけ関数型で書いて、副作用を少なくする 効率やどうしても副作用が必要なところは関数やマクロに閉じ込める というのが良いと思ってる。
賛成反対はともかく、それはなぜ?
>>592 卵の腐ったのが嫌いな人なんですが、同感です。
最初は、副作用が無い版をつくってチューニングしてだんだん形にしていく。
>>593 デバッグのやりやすさだと思うよ。手続き型の書き方を利用していくと
関数の作用が、複数にまたがるために、エラー箇所の見積もりが面倒になる。
一つくらいだったら、さほど問題はないけど、複数同じようになってみたら
ちゃっちゃと作っていく関数型スタイルを壊すだけになるんだよ。トレース
にしてもプロファイルにしても煮詰める箇所を定めやすい。
だから、一つ一つの関数の作りはシンプルでというのは、自分の中では鉄則。
でも、doなんて多様するとね。。。あとが大変なのよ。
do記法が嫌いな人って結構いるんだなぁ・・・意外
if 〜 then 〜 else 〜 と書けないのが悲しい
そんなのたった二つスペース入れるだけでいいじゃんかwww
13でHaskellの師匠を見っけたのか。 中学生でも関数型は可能だな。
A lot of people wonder if learning Haskell, a purely functional language, as a first language would make OOP languages be as difficult to learn and understand as functional languages are to OOP developers. My answer, given my experiences, is no. Learning a functional language first gave me the programming foundations that I needed to understand OOP and how it compared to other paradigms. と答えてるな。
関数型を最初に勉強したらOOPの勉強が困難になるかっていうとそんなことないお 関数型のおかげでOOPの習得に必要なプログラミングの基礎も身についたお だから初心者も関数型から入ったらいいお!Prolog最高だお! ってことか
>>600 Scratchは色々な国の小学生に使われているよ。
しかもSmalltalkで改造されたパーツが小学生間で流通してるよw
>>597 Haskell 2010では書けるようになった
今時は13歳はもうビッチってことだろw
template用途だと関数型言語は理にかなっているよね C++だってtemplateは純粋関数型言語だし まぁあれは構文が腐っているけど
テンプラと関係あるっけ?
>>597 むしろ、elseなしが書けないわけですが・・・
パターンマッチあるから、困ることもないんだが
612 :
デフォルトの名無しさん :2011/12/03(土) 09:21:52.54
そういう時はifじゃなくてwhenじゃない?
>>610 入力のソースを変形して出力するという処理だから関数型に適している
関数型「でも」できるってのと、 関数型「のほうが上手く」できるってのは ずいぶん違う話だぞw
しかも、関数型のストライクゾーンは狭いしな。ど真ん中だと最高なんだけどね
ど真ん中に来ないと打てないのは三流以下
>>615 ど真ん中にはショボいトイプログラムしかないけどな。
GCの停止時間とかシビアな性能が求められるプログラム以外は何でもいける
かつ、高速演算とか細かなIO制御だとかもしなければ
そんな事言ったらC言語だけでいいじゃん。
大規模データも勘弁
手続きでも関数型でもオブジェクト指向でもなんでも書ける言語も多いけどな。 人間だっていろいろな言語に対応できたほうが良いだろうに。 関数型は使えないとか、俺は馬鹿ですって言ってるようなもんだ。
読み書き出来て使いこなせるけど 馬鹿の一つ覚えみたいにそればかり使わない っていうのが一番尊敬出来るし信用出来る
他人に無理やり薦めない 強制しないってのもな 不況は勘弁
x不況 o布教
>>626 関数型言語使えるなら、コード書いてちょ
>>619 細かなIO制御は難しいが, 高速演算とかならLISPでもできるな
最近はそうでもないが, 高速演算/並列演算を最適化する研究は
FORTRANとLISP中心で行われていた
LISPは関数型じゃないって言ってしまえばそれまでだけど
「細かなIO制御」って言葉の意味が分からんけど、 語感から推測する限りでは別に関数型と相性が悪いようには思えない
IO制御っていうかメモリ管理のことじゃない? GCは、関数型言語でしか採用されてないわけじゃないし、 計算速度で言ったら、C言語かFORTRANしかいらないのかってことになるし、 批判が的外れなんだよね。
>>630 どうしてIO制御はメモリ管理のことだと思った?
どっかから謎電波を受信しちゃった?
関数型言語使うやつって、みんなこんな馬鹿ばかりなの?
>>631 ×)関数型言語使うやつって、みんなこんな馬鹿ばかりなの?
○)Haskell使うやつって、みんなこんな馬鹿ばかりなの?
関数型言語を使えない奴は馬鹿。 理解出来ないから、使えないことにしたいんだろ。
634 :
デフォルトの名無しさん :2012/01/21(土) 19:40:42.50
Haskellが得意な分野って何かある? 構文解析くらいか?
ハスケラが得意なのはアニメキャラの女装とオナニー。
>>631 IO制御を何のことだと思ってるだろう?
謎電波受信かw
やっぱ馬鹿だな。
本家Haskellスレでお前らtailも満足に書けない アホ呼ばわりされてるじゃんw tail -f じゃないよ?ただのtailだよ?
>>636 ねえ、どうしてIO制御はメモリ管理のことだと思い込んじゃったの?
哂ってあげるから正直に書いてみてごらん?
640 :
デフォルトの名無しさん :2012/01/22(日) 16:09:50.34
>>634 自分は+演算子と同じ動きする演算子を定義しようとして、数字から再定義してペアノの公理(succ)作っちゃったけど、数学とはすごく相性良いね
自然数しか扱えないのを作ったけど、整数・分数への拡張はすぐ出来る自身はある
少数は・・・カウンタブルな無限じゃないから、独自定義は無理かな・・・
柔軟性と実行速度だけなら、LLを上回ってると思うよ
(ghciやrunghcだとLLより遅いけど、コンパイルできる形にしてghcで実行ファイルにするとLLより100倍速くらいになる)
あと、LLが得意とする文字列処理はHaskellの方に軍配が上がる
Web系はLLよりHaskellで作ったほうが楽なんじゃなかろうか
構文解析と繋がるけど、こんなブログ記事もある
正規表現を超える
http://d.hatena.ne.jp/kazu-yamamoto/20090309/1236590230
>>641 succで四則演算から再定義して大量の整数演算しても
コンパイルすればLL言語よりも100倍速くなるのか?
にわかには信じられない話だなあ。
Haskellの文字列は遅すぎるだろ LLの文字列操作の方がずっと速い(Cで実装されてるし)
>>637 Haskellスレは実用より理論な人が集まってるからなあ
>>642 ただし、同じアルゴリズムに限る
が、頑張ればLLと同じアルゴリズムは書けるよ
自分は、アルゴリズムやデータ構造の専門家じゃ無いが、ググレばづぐ出るし、分かりやすい
(それを言ったら、Cの(ry)
>>644 seekしてファイルの末尾から順番に読む程度のコードが書けなくて
理論もクソもあるか
>>645 書けるかどうかじゃなくて、
Haskellでsuccで再定義された四則演算が
LL言語のビルトイン四則演算の100倍速いのかと
訊いているのだが?
>>647 そんなの、succのが遅いに決まってるだろ
HaskellのビルトインとLLのビルトインを比較しない理由は?
>>644 X 実用、理論
O ルーチンワーク、これから開拓
tailも書けないアホが何を開拓するの?
>>648 じゃあ何のためにsuccを定義するの?
>>651 haskellだと、あらゆるものを抽象化出来るって聞いたから、じゃあ+演算子と同じものを独自実装出来るんかいな?と、作ってたら、数字も抽象化する必要があって、知らん間にsuccになった
ありていに言えば、ただの興味本位だよ
you succ
>>652 ただの興味本位ってわけじゃないと思うぞ。
>>652 で、それがどうして「使える」ことにつながるの?
アルゴリズムを使いまわせる。 こういう基本的な関数を定義するのは、別に関数型にかぎらずに、 似たような処理をするところは、同じように書きましょう。 出来れば同じ関数を使いましょうってことで、そうすれば書く量も読む量も減って メンテナンスしやすくなる。
>>655 ?
使えるって?
succ自体は糞の役にもたたんよ?
言語としての抽象度が高いからこそ簡単に書けるんだろうなって書いてて思っただけで
抽象度w
今時succで四則演算を再定義できないってよっぽどいまいちな言語だろ 関数型言語の特徴とは思えんのだが
再帰的データ型を定義できるかどうかだろ?
色んな言語のsuccを見てみたい
Cだと厳しい、C++やGCのある言語なら余裕 別にHaskellである必要は全然ないな
既存の型とのマッピングを定義して、 その上でsuccやadd等を定義すればいいだけ。 typedef unsigned int nat; nat succ(nat n) { return n+1; } nat add(nat n1, nat n2) { if ((int)n1) return add(n1-1, succ(n2)); else return n2; }
>>663 それだとunsignedを使ってるから、自然数を自分で定義していない
>>664 じゃあunsignedを取ればいいw
まあunsignedがあろうがなかろうが、その構造をsucc関数で構成した上で
addを定義しているのだから、ペアノ自然数の実装として何の問題もない。
いやintとかunsignedとか使ったらさすがに自明すぎるんじゃね
2^32で循環してるから自然数の定義にならない
keep it simple and stupid
>>667 int=32bit とは限らないよw
ちなみに扱える自然数の数に上限があるのはHaskell等の関数型言語も同じ。
>>667 君が定義した自然数で2^128を求めてみてよw
多倍長整数にマップすれば問題ないが、
例えばHaskellあたりの代数データ型では無理だと思うよw
循環していたら公理と矛盾するだろ 有限のリソースをもった計算機上で全ての自然数を列挙できないのは別の話
ペアノ式の自然数の定義って 「自然数とは、0か、自然数の後者である」 をなるべく自然にプログラミング言語に翻訳したものだと思ってたけど違うの?
nat succ(nat n) { if(n == UINT_MAX)exit(-1); return n+1; } これで循環しない
>>670 Haskellは上限無いと思うんだけど、、、
どんな言語だろうが、計算機上のリソースは有限なんだから 必ず上限がある。 だから自然数は決して実装できない。
>>674 式の内部表現のグラフノードのポインタのビット数が決まっているからダメ
677 :
デフォルトの名無しさん :2012/01/26(木) 06:32:42.87
ペアノの公理が簡潔に書けても実用性とあまり関係ない。 「数学と相性が良い」ってのも同様。 MathematicaやMaximaはHaskellより よっぽど数学寄りだが使い道は限定されている。 構文解析と教育、マの趣味としては活躍する
>>663 +の逆演算である-を使っちゃいかんだろ
+も-も使わず定義汁
自分は元々+演算子の再定義でsucc作ったんだぞ?
つまり、-演算子も同時に再定義してる
+演算子を抽象化出来るか?が、自分のテーマだったから、既存の算術演算子(+,-,*,/,%)は使用しないのが絶対条件だった (さすがに=は使わないと定義出来ないんで使うけど)
Cならポインタ演算p++をsucにするのが無難では? つかこんなのC以外なら簡単。 その言語が使えるかどうかの指標にならない
zero = () succ = lambda x : (x,) pred = lambda x : x if x == zero else x[0] itr = lambda f, x, y: x if y == zero else itr(f, f(x), pred(y)) add = lambda x, y: itr(succ, x, y) sub = lambda x, y: itr(pred, x, y) mult = lambda x, y: itr(lambda z: add(x, z), zero, y) def quo_and_mod(q, x, y): r = sub(x, y) if r == zero: return (succ(q), zero) if x == y else (q, x) else: return quo_and_mod(succ(q), r, y) quo = lambda x, y: quo_and_mod(zero, x, y)[0] mod = lambda x, y: quo_and_mod(zero, x, y)[1]
結局、関数型言語由来の機能に頼ってる件
へー、何が関数型由来なのか言ってご覧? ちなみにクロージャは関数型由来じゃないよw
昔、オブジェクト指向にもケチ付けてる奴は居たよなあ
関数型にケチつけるつもりはないが Haskellこそ至高みたいな意見は鼻につく succが書けた程度で言われると特に
>>684 今でもオブジェクト指向にケチつけてるハスケラがいるねぇw
687 :
デフォルトの名無しさん :2012/01/27(金) 06:02:24.04
ほうなるほどなるほど
succどうしが等しいとか、どっちが大きいとか、比較出来るようにする仕組みはhaskellが楽
>>688 後出しかよ。
口だけじゃなくてその根拠となってる比較のコードを書いてくれ。
gt = lambda x, y: sub(x, y) != zero lt = lambda x, y: sub(y, x) != zero ne = lambda x, y: gt(x, y) or lt(x, y) eq = lambda x, y: not ne(x, y)
driving(Eq,Ord) この一行をsucc型定義の下に追加するだけ
>>692 いや、Ordはderiveするだけじゃダメだろ
Haskellの文法や型システムや勝ち抜きの比較が便利なだけで 関数型言語の特徴ではないような 仮に副作用を認めるunsafeHaskellみたいなものが存在しても 同じように書けるだろう MLやLISPみたいな手続き型の言語に対して関数型言語は参照透明という制約が増えているから ミスを減らせるとかの利点はあっても簡単にかけるってことはないんじゃないの?
>>694 え、MLもLispも一般的には関数型言語と言う認知だと思うけど。。。
まさかλ計算由来のラムダが関数型言語由来の機能じゃないとは言わないよね?
>>696 まさか、ラムダ計算が関数型言語由来だとか
馬鹿なことは言い出さないよなw
>>696 いやこのスレの上の方の流れだと
OCamlerがHaskellerを煽ってる感じだったから
MLが手続き的ねえ…面白杉
>>699 MLは手続き的だろ
定義すら上から順番に実行(?)される
ほう、ハスケルはEOFから逆順にでもパースされていくのかな?
Haskellは定義を任意に並べ替えてもプログラムの意味が変わらないってことだろ
>>696 ラムダがあれば関数型言語になるなら
今時の言語は大抵関数型言語になっちゃうんだが
perlやPHPやmatlabが関数型言語なのか?
>>705 行単位でシャッフルしたら構文エラー出まくりなんだがw
「定義」って書いてあるのが読めねーのかアホ
>>706 ラムダが有れば関数型言語とは言ってないだろ
ラムダが関数型言語由来の機能だと言ってるだけだろ
>>703 >
>>699 > MLは手続き的だろ
> 定義すら上から順番に実行(?)される
それは名前のスコープをどう定めているかの問題であって手続き型言語か関数型言語かとは別問題。
OCamlなどのML一族の言語は関数型原理主義の立場から言えば手続き型言語だけれど、関数型言語として認識しているのが(恐らく圧倒的な)多数派。
MLの場合、どうしても必要となればref型の変数を用いた破壊的代入が使えるというだけで、普段はほとんど使用せずに書かれているから。
(バグなどで異常終了した場合のデバッグ用の情報を自分で残したい場合なんかには、ref型への代入があるのはとても便利。
あれがなければ多くのLisp環境みたいに専用のデバッガやトレーサーが用意されてないとMLプログラムのデバッグ作業は難しいと思う)
なお、
>>696 の
> え、MLもLispも一般的には関数型言語と言う認知だと思うけど。。。
Lisp、特にScheme以外のポピュラーなLispを関数型言語という認識は今では少数派だと思う。
現実のLispプログラミングは昔からPROGフィーチャーをガンガン使った手続き的なコーディングが占める比率が高いからね。
Schemeにもグルーピングのためのbegin式があるが、他のLispにおけるPROGほどには使われているようには見えないし、
高階関数を用いたプログラミングの比率は恐らくSchemeは他のLispよりもかなり高いと思う。
(プログラミングの教科書や参考書を見ても、Scheme以外のLispに対するテキストは高階関数の活用なんかには
それほど力を入れていないのに対して、Schemeプログラミングの教科書は高階関数をどうやって活用するかに相当な比重を
置いて書かれているものが多い。特にIndiana学派の連中が書いたSchemeの教科書や参考書はその傾向が顕著)
>>711 名前のスコーピングだけの問題じゃねーだろ
IOだって副作用なんだからref使わなくても順序は発生する
これ実行してみろよ
let f () = print_endline "aaa"
let _ = f ()
let f () = print_endline "bbb"
let _ = f ()
schemeのトップレベルのbeginは少なくとも((lambda()))には変換できない マクロは1つのリストしか返せないので複数のトップレベルdefineを 行うマクロを実現するにはbeginは特殊化されてないといけない CLではどうだったかな
あ、副作用抜きでそういう仕組みが要るという話ね
純粋関数型言語は使えない LispやMLはどうでもいい
>>712 IO に使うファイルハンドラが ref そのものだろ
>>716 out_channelの型は隠蔽されてるからOCaml的にはref型じゃないだろ
それに
>>711 はそういう意味でref型って言ってないと思うぞ
> MLの場合、どうしても必要となればref型の変数を用いた破壊的代入が使えるというだけで、普段はほとんど使用せずに書かれているから。
それともMLではIOは殆ど使用せずに書かれてるのか?
MLは let x1 = e1 in let x2 = e2 in e3 と let x2 = e2 in let x1 = e1 in e3 で意味が変わるんだよね。
正格評価だからね
>>718 MLにおいて式が順番に評価されることは
「名前のスコープをどう定めているかの問題」ではない
let f () = print_endline "aaa" let _ = f () let f () = print_endline "bbb" let _ = f () これを IO モナドを使って Haskell で書いたら順序の問題が発生しないの?
「MLにおいて」というのが意味不明ってこと
関数型言語であり、かつ手続き型言語でもある、というのが無難な落としどころだろう
>>719 ML(Standard ML)の場合:
let val x=1 in let x=2 in x end end (* Result: 2 *)
let val x=2 in let x=1 in x end end (* Result: 1 *)
Haskell(Gofer)の場合:
let x=1 in let x=2 in x -- Result 2
let x=2 in let x=1 in x -- Result 1
MLは意味が変わるけど、同じくHaskellも意味が変わる
>>720 上で示したように、非正格評価であるHaskellも(スコープの変化に応じて)意味が変わる
>>721 の指摘が正しい
おそらく
>>719 ,720は正格評価/非正格評価の意味を誤って解釈していると思われる
>>724 つまり、do記法を構文糖として定義しているHaskellは、
関数型言語であり、かつ手続き型言語でもある、というのが無難な落としどころなのですね
たいへんわかりやすいです
>>726 は変数束縛の隠蔽をしてるからHaskellでも意味が変わる
これはスコープの問題
>>719 の例とは違うだろう
関数型言語スレからコピペ
>334 名前: 283 Mail: sage 投稿日: 2011/09/29(木) 18:17:12.26
>
>>298 ,323
>
>FP
> ---- 壁0. 変数の壁 ----
>Haskell
> ---- 壁1. 純粋性(副作用)の壁 ----
>SML/OCaml
> ---- 壁2. 型推論の壁 ----
>Scheme
> ---- 壁3. 末尾再帰最適化/局所定義式の壁 ----
>========<< 越えられない壁 >>========
>Smalltalk/Ruby
> ---- 壁4. 条件判定式の壁 ----
>Perl/Python/JavaScript
> ---- 壁5. クロージャ/ラムダ式の壁 ----
>========<< 越えられない壁 >>========
>C/C++/Java...etc
let x = M in N ってのは、MLなら x = M; N だが、Haskellなら #define x (M) N; ということだな。 #define の順序を入れ替えても意味は変わらない。
731 :
726 :2012/01/28(土) 10:19:22.14
>>728 では、変数束縛を隠蔽しないコードの例だ
こちらの例のほうが、(
>>726 よりも)
>>719 の例に近いだろうと思う
ML(Standard ML)の場合:
let val x=1 in let val y=2 in x-y end end (* Result: ~1 *)
let val y=2 in let val x=1 in x-y end end (* Result: ~1 *)
Haskell(Gofer)の場合:
let x=1 in y=2 in x-y -- -1
let y=2 in x=1 in x-y -- -1
変数束縛が隠蔽されなければ、MLもHaskellも意味は変わらない
もし反論あるなら、MLとHaskellで結果が変わる(
>>719 ではない)例の提示をキボン
>>727 do
a <- x
b <- y
return a + b
これは次の構文糖だよ?
x >>= (\a -> y >>= (\b -> return a + b))
順序を関数合成で表すからこそ純粋関数型言語なわけよ
MLは順序を関数以外で表現するから手続き型言語と言われるわけ
>>730 >だが、Haskellなら
>#define x (M)
>N;
>
>ということだな。
>#define の順序を入れ替えても意味は変わらない。
いったい、とことどこを「入れ替えた」の?
日本語として意味不明な文章だ
>>701 前書いたのそのままで良ければ
-- 自然数を定義
data NaturalNum = Zero | PlusOne NaturalNum
deriving (Eq,Ord,Show,Read)
-- 加算を定義
Zero +^ n = n
m +^ Zero = m
m +^ n = inc m +^ dec n
-- 減算を定義
Zero -^ n = n
m -^ Zero = m
m -^ n | m == n = Zero
m -^ n = dec m -^ dec n
-- インクリメント(1+)を定義
inc n = PlusOne (n)
-- デクリメント(1−)を定義
dec (PlusOne (n)) = n
-- 自然数を独自自然数へ変換
int2NaturalNum 0 = Zero
int2NaturalNum n = PlusOne (int2NaturalNum (n-1))
-- 独自自然数を自然数へ変換
naturalNum2int Zero = 0
naturalNum2int n = 1 + naturalNum2int (dec n)
>>733 $ cat a.txt
#define F(UNIT) print_endline "aaa"
#define UNDER_SCORE F(UNIT)
#define F(UNIT) print_endline "bbb"
#define UNDER_SCORE F(UNIT)
$ cpp a.txt
# 1 "a.txt"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "a.txt"
遅延評価では何もしない
>>732 ML(Standard ML)で順序を表すには、;(セミコロン)演算子を使う
そして、
>>732 のような手続きの表現には、;演算子と参照型を組み合わせる
! a x ; ! b y ; a + b
ここで、;演算子は2引数で常に後者を返すという、まさしく関数であるけれど、
はたして
>>732 の目には、 ;演算子が「関数以外」の何に見えているのだろうか?
>>736 自分で参照型「も」使うって書いてるじゃん
ハスケル以外はみんな不純!
不純だから劣ってるって話でもないんだけどね
>>738 MLが参照型「も」使うから手続き型であるというのなら、
「関数以外」の do「も」使う Haskell も手続き型ということになるよね
それともHaskellにとってdoは関数なのかな?
その場合、関数doの型定義(定義域と値域)は?
doは只の構文糖だけど、refって構文糖なの? いや、MLはHaskellのdoの中にずっと居るようなもんだと 思えばそうなのか?
>>737 もちろん二つのref型への代入を入れ替えれば、意味が変わるのは当然の事
そして、Haskellにはそもそもref型が存在しないから、入れ替えを行いようが無い
で、何を言いたいの?
MLのrefはデータ型ですよ 関数ではありません Haskellのdoが(「関数以外」の)構文糖であるように....
ただの構文糖のdoを指して「関数以外のものを使ってる」という
>>741 は意味不明
表記法法が違うだけで使ってるのは関数
裏でこっそり副作用起こしてる「純粋な」関数w
>>732 > x >>= (\a -> y >>= (\b -> return a + b))
Haskell わからんのだけど、これって
(lambda a -> (lambda b -> a + b) y) x
と何がちがうの?
>>744 >
>>719 で結果が変わる(かつ未定義にならない)のはMLが正格評価だから
違うだろw
>>719 で結果が変わるのは参照型への代入を使った例外的な場合のみ
それ以外の一般的な式においては、(Haskellと同様に)意味は変わらない(
>>731 を参照)
Haskellで意味が変わらないのは、参照型が存在しないので入れ替えようがないから
その代わりに(MLにはない)doという「関数以外」のモノが存在する
そして、do記法の中で式を入れ替えれば(MLと同様に)意味が変わる
結局、ここまでの手続き的か否かという議論の中で、正格評価/非正格評価の違いは無関係
あえて関連性を言えば、
非正格評価であるHaskellでは参照透明性がくずれるref型を導入「できない」から、
do記法という「関数以外」の異物を導入した
という点かな
>>746 Haskellの do が「ただの構文糖」にすぎない、というのなら、
MLの ref も「ただのデータ型」にすぎない、としないと
>>746 は矛盾を抱えるよね?
>>749 let x = ref 0
let f () = x := !x + 1; !x
let a = f () in
let b = f () in
a - b
へー、これで a - b が決定されるのは正格評価と関係ないんだ
あとdoは構文糖だっていってんだろ
表記が違えば関数じゃなくなるのかよ
>>747 机にかじりついて勉強ばかりしている頭でっかちよりも、
時には裏でこっそり「不純な」xx交遊するほうが、生きていて楽しいよねw
私は純粋で品行方正ですなんて、どこかの政治家みたいでかえってうさん臭い
>>748 >>=は二項演算子だから、bind という関数に置き換えて書くと
bind x (lambda a -> bind y (lambda b -> return a + b))
それただの言い換え・・・ bind って関数の定義を教えてほしいんですけど・・・
>>752 じゃあこれは?
let a = f () in
let b = f () in
print_int b;
print_int a;
a - b
>>755 bind :: [a] -> (a -> [b]) -> [b]
>>748 >>=は二項演算子だから、bind という関数に置き換えて書くと
bind x (lambda a -> bind y (lambda b -> return a + b))
あれ?何で前に書き込んだ内容が...?
760 :
749 :2012/01/28(土) 11:36:37.96
>>751 >へー、これで a - b が決定されるのは正格評価と関係ないんだ
うん、関係ないよ
関係するのはref(参照型)の使用
繰り返しになるけど、refを使わなければ意味はHaskellと同じ(
>>731 を参照)
あとrefは「ただデータ型」だっていってんだろw
>>756 関係ないよ
正格と非正格で評価順序が違うから、
副作用のある式を評価すれば当然結果は変わるけど、
正格でも非正格でもそれぞれの評価戦略に従って a - b の値は一意に決定されるよ。
参照透過で停止するならチャーチロッサー性により結果は同じ
>>761 だからrefを使っててもa - bが定まるのは正格評価だからだろ
a = f () と b = f () のどっちを先に評価するかで結果変わるんだから
もし print_int で出力する時点で評価する遅延評価なら
結果が変わっちゃうだろ
>>763 >a = f () と b = f () のどっちを先に評価するか
それはマイナスという二項演算子の定義の問題
正格評価と全然関係ない
参照透過ならまぁそうだね。
MLは参照透過じゃないからね
haskellもリストは、完全に参照透過じゃないと思うけど、、、
Haskell は建前参照透過とでも言ったところか
>>766 []はリストじゃない?
一般的には (>>=) :: m a -> (a -> m b) -> m b じゃないの?
Haskell知らんけど(定義はwebからコピった)
OCamlなら
(>>=) : 'a t -> ('a -> 'a t) -> 'a t
return : 'a -> 'a t
771 :
749 :2012/01/28(土) 12:05:23.04
>>763 だからrefを使わなければ、正格評価でも非正格評価でも結果は同じ(
>>731 を参照)
そしてrefが使えば結果は変わるけど、そもそもrefの存在が許されるのは正格評価だけで、
非正格評価では(参照透明性が崩れる)refの存在は許されない
もしも非正格評価でrefが使えてかつ結果が同じであれば、
その理由が正格/非正格の違いであると考察する事は正しいと思う
しかし、残念ながら非正格評価ではrefが使えないから、比較そのものが成立しない
従って、両者の差異を決定付ける要因とは、refを使う/使わないという違いであると結論付けられる
ハァ、疲れたョ
ここまで書けば納得してもらえるかな?
let x = ref 0 let f () = lazy (x := !x + 1; !x) let (!$) x = Lazy.force x let a = f () in let b = f () in print_int (!$ b); print_int (!$ a); (!$ a) - (!$ b) lazyで遅延評価するとref型を使ってもletの順番には異存しないよ
極端なこと言えば、 非正格評価のメリットって無限リストを扱えることだけじゃん。 それだけのために失っているものが大きすぎじゃね?
他にも色々なボトムを回避できるけど?
ここまで説明されてもさっぱりわからない いや、判ろうとしないだけだ なんつって なんつって orz
>>766 汎用のリスト型(aとかbとかのちゃんとした名前は代数型とか何とか言ってた気がする)
リストの中身はどんな型でもおk(ただし、中身各要素の型は同じ型で統一しないとダメ)
c++のテンプレートとか、c#,javaのジェネリックみたいなもん
a
最近、アンチスレが隔離スレとして機能してないので他のスレが迷惑な件。
今c#使ってて のvarを覚えた var という暗黙の型を持つことができます。 暗黙的に型指定されたローカル変数は、型を宣言した場合と同様に厳密に型指定されますが、コンパイラが型を決定します。 次に示す 2 つの i の宣言は、機能的に同じです。 とのことことだが関数の人これどう思う? static関数でvar でやってけば関数っぽくなるのでは?
var を メソッドのシグニチャに記述はできないが、できるようにしたらという意味かな。 F# はそういった実装になってる。
問題はvar とジェネリクス、ラムダを合わせるとお互いに型推論しあってうまいこといかないこと
そう言えば、双方向リストはzipperを使わなくても、 タプルとリストで実現できるって、どっかで見かけた。 ([3 2 1],[4 5 6]) ポインタを動かす→([4 3 2 1],[5 6]) ([2 1],[3 4 5 6]) 方法を取るってことだた。
双方向リストにする意味ねえだろ、それw
null ってどう思う?
C言語のstrlen関数の初心者にも分かり易い実装 int my_strlen(char str[]) { int i = 0; for( i = 0; str[i] != '\0'; i++ ) ; return i; } Haskellのlength関数の初心者にも分かり易い実装 my_length [] = 0 my_length (x:xs) = 1 + my_length xs とか見てて思うのは、何というか、実用的とかは知らんけど、(広い意味での)アルゴリズムを学ぶのにHaskellは向いてると思う HaskellのコードとCのコードが同じアルゴリズムで動いてることに気づけば、他の言語でも同じアルゴリズムが使える事が期待できると思う ところで、CやHaskellみたいに組み込み関数を自分で実装してみようと言う試みが、rubyやpythonではあまり見られないんだが・・・ 難しいんだろうか・・・
その例で、C版とHaskell版が同じアルゴリズムに見えるようなら、 まずは自分がアルゴリズムの勉強を勉強してみるべきだと思うがw
>>786 ほう、では、アルゴリズムとして違う点を述べよ
スタック消費するとか、そう言う点はアルゴリズムとは無関係だぞ
>>785 これ本質的には一緒だよね。
あと、ループで書くか再帰で書くかの違いで、言語は関係ない。
Haskell以外はどちらでも書ける。
ただ、初心者には、ループで教えるほうがいいよ。
再帰は、末尾再帰最適化されてない言語だとスタック溢れさせてしまって、
余計なところで躓くよ。
>>788 >再帰は、末尾再帰最適化されてない言語だとスタック溢れさせてしまって、
まあそのとおりなんだけど、その理屈だとCはアルゴリズムを学ぶのに適してない言語という事になってしまうな。
Cならループで書くだろ
>>790 Cでなら、ループで教えると言うことと、アルゴリズム教えるのにCは向いてないと言うこととは無関係ですが・・・
ループで書くんだからスタック溢れたりしないだろ
スタックが溢れない事と、アルゴリズムをCで教えるのには向いてないのは無関係ですが・・・
うちの GHC 7.0.4 では次のコードはスタックオーバーフローで落ちる my_sum n = f n 0 where f 0 m = m f n m = f (n-1) (m+1) main = putStrLn $ show $ my_sum 1000000 Haskellは遅延評価だから末尾再帰で書くだけじゃ不十分なことがある そういうことも含めて初心者に教えるのは難しいだろう
>>795 と言うか、初心者がそんなでかい数字使うかいな
個人的にはHaskellでアルゴリズムを学んで、Cなり普通の言語でそれを活用する。という形を期待してる
そのアルゴリズムがどういう動きをしてるのか?が見えやすいのはHaskellだが、実用には、やはり他の言語が向いてる
>>795 これ特に問題なさそうなのになんで落ちるんだろう?
>>797 fが第二引数に関して正格であることをGHCが見抜けないから。
-Oを付ければ落ちない。
遅延評価は初心者にはキツいと思う
考えなきゃいけないことが一つ増える
逆に実用レベルなら
>>795 みたいなのに対処する方法はいくらでもあるし、
プログラマにもそれができることが求められる
>>787 C版は連続メモリ領域の中で、数え上げによるトラバースをして、特定要素として記述された末尾記号を探索している。
Haskell版は代数データ型が提供する木構造の中で、パターンマッチングによるトラバースをして、代数データ型で定義された末尾記号を探索している。
全然違うw
-Oつけたら落ちないのか むしろそっちが驚きだわ
>>800 CのクイックソートとHaskellのクイックソートも全然違うアルゴリズムってか
使ってるデータ構造が違うだけで、アルゴリズムは同じだろ
>>802 ランダムアクセス可能な領域を使うのと、単方向リンクによる木構造を使うのと、
同じアルゴリズムとか言い出すのか?
アルゴリズムの基礎からやり直したら?
おいおい、じゃなんで同じクイックソートって名前がついてんだよw 日本語の基礎からやり直したら?
アルゴリズムの同一性なんて決定不能であることが証明されてるだろw 単にカタログ化するための名称で「同一アルゴリズム(キリッ」ですかwww
>>805 アルゴリズム(クイックソート)と、データ構造(配列・リスト)を一緒くたにするな
え、アルゴリズム評価でランダムアクセスメモリが前提かどうかって、すごく重大な要素だが? おばか?
>>810 それデータ構造の話で、アルゴリズムの話じゃ無いじゃん。
あほか。
>>810 適切なアルゴリズムに適切なデータ構造を選択するのは確かに重要で、リストはHaskellに限らず、配列を使ってクイックソート書くよりも短いコードになるが、配列を使ったクイックソートよりも遅くなる
だから、アルゴリズムとデータ構造を一緒くたにするなと言ってる
プログラム = アルゴリズム + データ構造
あらいぐまパスカル乙
ハスケル パスカル 名前もそっくりだしな。
>>811 えっと、あんた、メモリモデルって聞いたことある?
アルゴリズムの本なら大抵は説明しているはずだが…
>>812 メモリモデルが異なる言語間で同じアルゴリズムとか、あんた高卒?
ここの言葉が荒い奴って、思慮深さが全くないし、底の浅い人間の典型 みたいなコメントばかり繰り返してるな。隔離スレらしいといえばそれまでだがな。
>>816-817 そうかい
メモリモデルとやらは知らんが、日経ソフトウェアやら、関数型言語の本には同じクイックソートとしてCやJavaと関数型言語のコードが平然と比較されてるぞ?
クレームよろしく
>>820 馬鹿を認めるから、メモリモデルっての説明してくれ
単なる感だけど、アルゴリズムの性能比較の用語か何か?
それともアルゴリズムの厳密な定義として
>>805 みたいなのが決まってるの?
アルゴリズムって、配列使うとか、リスト使うとかに依存しない、もっと抽象的なものだと思ってたんだが
>>821 アルゴリズムを記述する仮想機械のモデル。
ランダムアクセス可能であることが前提ならば、
そのメモリモデルはランダムアクセスモデルと呼ばれ、
仮想機械はランダムアクセスマシンと呼ばれる。
一方、磁気テープやストリームデータのように
逐次的にしか読み書きできないものもある。
それらはランダムアクセスモデルとは区別される。
で、Cの配列はどっちで、Haskellのリストはどちらか
理解できるよな?
>>822 こいつホンマもんのあほや。
初心者が混乱するからやめろ。
関西弁つかっとるとうるさいレイシストがくるでぇ〜 きーつけや〜
ランダムアクセスできない仮想機械で Cのコードを走らせたらどうなるのっと
計算量のオーダが変わる
>>822 うーん。。。
データ構造によって実現方法が変わるって言う、当たり前のこと言われてるだけの様な。。。
人間が書類の並び替えにクイックソート使った場合はどっちのモデル?
ランダムアクセス出来るから、Cと同じ?
分割/結合が容易だから、haskellと同じ?
rubyの配列は動的に要素数を変えられるから、ランダムアクセスしながら、haskellっぽく書けるけど、Cと同じモデルなの?
O(1)で書類にアクセスできるようになりたいものだ
ページ番号指定されても二分探索くらいはしないといけないからな人間は
Haskellでreverce関数書くとこうなるけど、 reverce [] = [] reverce (x:xs) = reverce xs ++ [x] rubyとかpythonとかだと、reverce関数はどう書くの? この辺、命令型言語と宣言型言語の違いが出てきそうな気がする
def reverse(lst): return [] if lst == [] else reverse(lst[1:]) + [lst[0]] def reverse(lst) lst == [] ? [] : reverse(lst[1..-1]) + [lst[0]] end パターンマッチング以外は見ための違いはほとんどないね
>>831 832とどっちが効率的かはわからないが。
def rev(l,a=[])
l.inject([]){|a,i|[i]+a}
end
p rev([3,4,5,1,2])
pythonなら、こっちのほうが数十倍速い def rev(l): return [l[i] for i in reversed(xrange(len(l)))] reversedが反則だというのなら、 def rev(l): return [l[i] for i in xrange(len(l)-1,-1,-1)] でも同じ。ちょっと見た目が不精ったいだけ。
PythonとRubyともに(程度の差はあれ)関数型の概念を取り込んだ (比較的)新しい言語だから、単純なreverse関数くらいだと、 手続き型言語(命令型計算モデル)と関数型言語(作用型計算モデル)との違い は出てこない 同じお題で、FortranやPascalで書けば、違いが分かるのかもしれない
>>835 お言葉ですが、
70年代後半に設計されたSmalltalk-80ですら
>>834 のような定義が可能ですが何か?
>>836 まず、オリジナルのSmalltalk-72は関数型言語である
LOGOをヒントに生まれたと伝えられてる
その後、(Smalltalk-76を経て)当時のXROX PARCで広く使われていた
Lispの影響を受け、より洗練された構文のSmalltalk-80が誕生した
だから、Smalltalk-80が関数型作法で書けるのは、ごく当たり前の話
さらに、関数型言語のルーツであるLISPそのものは60年代に誕生している
これはFORTRANやCOBOLの誕生時期とほぼ同じ
つまり、関数型言語そのものは古い技術である、と言える
>>831 関数型言語使いなら普通にfoldlを使おうぜ
reverse = foldl (\xs x -> x:xs) []
(脱線ついでに
>>837 の続き)
なお、有名なシステムブラウザ画面に代表されるSmalltalk-80のIDE(統合開発環境)であるが、これは
これまたPARCで広く使われたMesaと呼ばれる手続き型言語で書かれたシステムの影響を受けている
また、Smalltalk-80と同時期に誕生したInterlisp-Dにも同様なIDEの研究成果が反映された
結果として、80年代前半のPARC内には、Mesa/Interlisp/Smalltalkという
三つの(パラダイムの異なる)プログラミング言語コミュニティが存在することになった
(他にはCの祖先にあたるBCPLもファームウェア記述用に使われていた)
当然の事として、PARCでは次世代のプログラミング言語について熱い議論が交わされた
そして、最終的に主力言語として決定したのが(Mesaをベースとした)手続き型言語Cedarになる
つまり、80年代前半時点のXEROX PARCで選ばれたのは、
(このスレ的には残念な事であるが、関数型言語ではなく)手続き型言語ということになる
(....などと、無理矢理スレタイに戻してみた)
>>837 へ?状態の塊とも言えるLOGOをヒントに関数型言語設計したってこと?
Smalltalk-72にはしっかり「代入」がある上に、
クロージャにいたってはSmalltalk-80ですらナンチャッテ実装だった。
というわけでSmalltalkを関数型言語の傍流であるかのように言うことは
関数型厨の我田引水と言うほかない。
>>839 > (このスレ的には残念な事であるが、関数型言語ではなく)手続き型言語ということになる
おいおい、スレタイ読めよ。残念どころか、非常に歓迎すべきことだろw
Smalltalkのオブジェクトにメッセージを送ってその内部状態を変化させるというスタイルは 代数を基礎とする関数型とは相容れない気がするな
>>841 >へ?状態の塊とも言えるLOGOをヒントに関数型言語設計したってこと?
ん?何か(
>>841 を)読み違えているよ
まず、LOGOはタートルグラフィック機能ばかり注目されるけど、立派な関数型言語だよ
LISPのcar/cdr/consに相当するリスト処理もプリミティブとして言語仕様に定義されている
実際、LOGOが国内で注目された80年代当時、「LOGOによる記号処理」とか
「LISPとLOGOによるAIプログラミング」のような題名の本が出版されている
そして、(初期の)SmalltalkはLOGOの影響を受けている
まあ、LOGOが関数型言語であると聞いて驚く人が普通だから、
>>841 の疑問もしかたがないね
もしもこれがご不満なら、Wikipedia(日本語版および英語版)の訂正もヨロシク
>Smalltalk-72にはしっかり「代入」がある上に、
Smalltalk-80にもしっかり「破壊的」代入があるし、もちろんLOGOやLISPにもあるけど何か?
それとも
>>841 は「破壊的代入のあるLISPは関数型言語ではない!」と主張する
純粋関数型原理主義者、通称「ハスケラ症」の患者さんなのかな?(
>>15 )
>というわけでSmalltalkを関数型言語の傍流であるかのように言うことは
誰もSmalltalkが関数型言語であるとは言っていないと思うけどなあ....オブジェクト指向言語だろ?
ただし、SmalltalkがLISPやLOGOといった関数型言語から影響を受けたのは事実だし、
実際に、条件分岐が式であり、しかもブロック式(という「ナンチャッテ」クロージャ)があるから、
手続き型言語では素直に書けない関数型プログラミングのコードがSmalltalkでは書ける、というだけ
845 :
844 :2012/02/22(水) 14:56:25.07
訂正
X: ん?何か(
>>841 を)読み違えているよ
O: ん?何か(
>>837 を)読み違えているよ
昔はモナドなんかの研究が進んでなかったので 副作用がないとまともなプログラムは書けなかったから 関数型言語も副作用を許していたわけで (Common)LISPやMLみたいな言語は今となっては中途半端で 純粋関数型のHaskellが最強言語 みたいなラディカルな姿勢を皮肉っていたのがこのスレの上の方の流れだった
>>844 LOGOがLISPの影響を受けたのはその通りだが、それをもって関数型言語というのはあまりにも乱暴だな。
LOGOが受けたLISPの影響は主にその動的環境であって、関数型パラダイムではないだろう。
そもそもプログラム実行でのデータ処理の基盤が関数適用か代入かという区分を考えれば
LISPのsetやsetqはあくまで環境設定にすぎずプログラムの実行は関数適用にあることは明らか。
その点でタートルの状態変化をプログラム実行の基盤に置いているLOGOは全く別物だ。
Wikipediaを聖典のように持ち出すのであれば、LOGOが手続き型言語の例として挙げられている点をどう説明する?
>>847 要するに、純粋関数型原理主義者なのね....orz
>LOGOが受けたLISPの影響は主にその動的環境であって、関数型パラダイムではないだろう。
だから、動的な対話型プログラミング環境もLISPの影響だろうと思うけど、
>>844 で書いたように、
LOGOには、古いLISPの仕様に相当する関数型言語としての要素が備わっている
>その点でタートルの状態変化をプログラム実行の基盤に置いているLOGOは全く別物だ。
だから、LOGOの開発目的が教育用途であり、その応用であるタートルグラフィックが主体であると
考えてしまうのは、一般人であればしかたないと思うけど、グラフィックはI/O機能の一つでしかない
計算モデルという視点で見れば、LOGOは関数型言語なんだけどね
>>847 の考え方は、「木を見て森を見ず」そのものだよ
>Wikipediaを聖典のように持ち出すのであれば、
Wikipediaは聖典じゃないよ....当然だろ?
特に日本語版はソースも無しにいきなり著者の主観で始まる記事があるから、驚く事もある
でも、英語版はとりあえず全世界の人々に認められている事、さらに該当記事の冒頭では、
" It was originally conceived and written as a functional programming language,[1]" と
ソース付きで明記されている
これらから、LOGOが関数型言語の一つであると見なすのは、妥当な判断じゃないかと思うけどな
なお、冒頭の後半にはタートルグラフィックについて、こんな一文もある(ただし、こちらはソース無し)
"Today it is remembered mainly for its turtle graphics,"
>LOGOが手続き型言語の例として挙げられている点をどう説明する?
まずは、その例についてソースをキボン
849 :
848 :2012/02/22(水) 16:44:56.13
一部、変な日本語なので、訂正 X: だから、LOGOの開発目的が教育用途であり、その応用であるタートルグラフィックが主体であると 考えてしまうのは、一般人であればしかたないと思うけど、 O: だから、LOGOの開発目的が教育用途であるのは事実であり、その応用であるタートルグラフィックが LOGOの主体であると考えてしまうのは、一般人であればしかたないと思うけど、
originally って書いてあるじゃん…
>>847 LOGOが関数型言語であるというソースについて、
>>847 から異論があったので、別のソースを見つけてきた
・Computer Science Logo Style Volume 1: Symbolic Computing
Brian Harvey, University of California, Berkeley, MIT Press
http://www.cs.berkeley.edu/~bh/v1-toc2.html この本の序文(Preface)にある章 "Why Logo?" から引用する
・ It is a dialect of Lisp, the language used in the most advanced
research projects in computer science, and especially in artificial intelligence.
・For example, APL is based on the idea of matrix manipulation;
Prolog is based on predicate calculus, a form of mathematical logic.
Logo, like Lisp, is based on the idea of composition of functions.
・A big change since 1984 is that Logo is no longer the only member of
the Lisp family available for home computers.
Another dialect, Scheme, has become popular in education.
この本には高階関数の例としてmapの実装コードも紹介されている
この本でもまだ異論はあるかな?
>>847 もし英語が苦手なら、上の英文を翻訳してもいいよ
では、引き続き「LOGOが手続き型言語の例として挙げられている」ソースの提示をヨロシク
>>848 関数型言語は純粋でなければならないなんて思っちゃいないけど、
自分の基準では、関数型言語は関数適用を情報処理の主要な機構とした言語。
その点においてLISPも関数型言語。
LOGOにおいて関数適用は補助的な機構であり、主要機構は代入。
その点においてLOGOは関数型言語ではない。
LISPを関数型言語として認める人を純粋関数型原理主義と呼ぶのであれば、
それまでの話だけど。
また訂正
X: LOGOが関数型言語であるというソースについて、
>>847 から異論があったので、別のソースを見つけてきた
X: LOGOが関数型言語であるというWikipedia上のソースについて、
>>847 からWikipediaの信頼性に異論があったので、別のソースを見つけてきた
855 :
836 :2012/02/22(水) 17:41:24.68
こうして見ると、proceduralとfunctionalは実は排他的対立軸ではないとすら言えるし、
>>835 への指摘としては「新しい」という部分だからLOGOがLISPからインスパイアされていても
実はどうでもいいことではある。
しかし、LOGOはfunctional programmingというのはどうかと思うね。
starlogoを見てもfunctionalとは到底思えない。
せいぜい、originally designed upon a functional programming environment程度じゃなかろうか。
LOGOが関数型言語かどうかは まぁともかくとしてw 教育を目的とした言語であるLOGOが関数型プログラミングのスタイルで 実際にプログラミング教育に使われた例があるとしたら興味深いよね 他の言語や数学の知識のない小学生とかがすんなり関数型を受け入れられるのだろうか?
アメリカでは「失敗だった」ってのが定説ですな。 知り合いにも10人ぐらい実体験者がいるが、あまり肯定的な話ではなかった。
>>856 つまり、
1. LISPは関数型言語である
2. LOGOはLISPの1つの方言である。
3. したがって、LOGOは関数型言語である。
と言いたいのか。
その論だと、
1. Smalltalkは動的プログラミング環境である。
2. GNU SmalltalkはSmalltalkの1つの方言である。
3. したがって、GNU Smalltalkは動的プログラミング環境である。
という主張も正しいことになるが、それでいいのかい?
>>852 >LOGOにおいて関数適用は補助的な機構であり、主要機構は代入。
>その点においてLOGOは関数型言語ではない。
えーと、その為にわざわざ
>>851 というソースを提示したのだけど、読んだの?
読んだ上で「LOGOにおいて関数適用は補助的な機構であり、主要機構は代入」なの?
それとも、英語が読めない人?あるいは、自分が認めたくない事実には必死で目をつぶる人なの?
よく分からんなあ......
繰り返すけど、LOGOのタートルグラフィックはI/O機能の一部でしかなく、
言語の本質である計算モデルは関数適用であり、代入は構文糖にすぎない
>>851 の章 "Why Logo?"から、Schemeとの差異に関する記述を引用する
The main difference between Scheme and Logo is that Scheme is more consistent
in its use of functional programming style. For example, in Scheme, every procedure is
what Logo calls an operation--a procedure that returns a computed value for
use by some other procedure. Instead of writing a program as a sequence of instructions,
as in Logo, the Scheme programmer writes a single expression whose complexity takes
the form of composition of functions.
The Scheme approach is definitely more powerful and cleaner for writing advanced projects.
Its cost is that the Scheme learner must come to terms from the beginning with
the difficult idea of function as object. Logo is more of a compromise with the traditional,
sequential programming style. That traditional style is limiting, in the end,
but people seem to find it more natural at first. My guess is that ultimately,
Logo programmers who maintain their interest in computing will want to learn Scheme,
but that there's still a place for Logo as a more informal starting point.
あと、
>>854 は別人さんだと思うので、
「LOGOが手続き型言語の例として挙げられている」ソースの提示も忘れずに、ヨロシク
>>860 >1. Smalltalkは動的プログラミング環境である。
>2. GNU SmalltalkはSmalltalkの1つの方言である。
>3. したがって、GNU Smalltalkは動的プログラミング環境である。
この三段論法は、論理的に成立しないよ
命題1.は環境に関する事実だけど、命題2.は言語に関する事実
これらの型が一致していないから、単純に推論3.は誤り
詭弁を操ろうとするなら、もう少し論理学について勉強しておくれ
こちらが楽しめないからw
>>856 あなたの主張は、Smalltalk-80で関数型的な表現が可能なのは、
Smalltalk-72の時点でLISP発LOGO経由で
LISPの関数プログラミングのエッセンスが導入されていたからだと。
しかし、私の理解が正しければ、Smalltalk-72のmapはcollect:ではなく
do:相当なわけで、確かにLISPのmapからの派生には違いないと思うが
関数プログラミング的なmapではなく、手続き的(doneで終わるところが
特に)なmapだと思うのだが、どうよ?
具体的には、
>>834 的なコードを
Smalltalk-72のmapでどう実装するか、
その実装は関数プログラミング的か、
ということだが。
>>862 LISPやSmalltalkの議論に「型が一致していない」というのは冗談としても、
Smalltalkの歴史うんぬんを言う割に、言語としてのSmalltalkと環境としての
Smalltalkをバラバラにするのかい?
自分としては一貫してLISPもLOGOもSmalltalkも言語であり環境でもある
ものとして記述してきたつもりだが。だからLISPとLOGOの関係を動的環境
を軸に書いたのだが。
歴史を振り返るのは結構なことだが、ある言語が新しい言語を派生する時には
必ず新しい言語には元の言語では適応できなかったニッチを獲得していること
を忘れないほうがいいんじゃないのかい?
型が一致しないというのなら、それこそLISPのmapとSmalltalk-72のmapと
Smalltalk-80のcollect:とpythonのリスト内包表現はそれぞれ別々の型だろうに。
ということは、
>>862 が正しいのなら
>>837 こそ詭弁なんじゃね?
>>863 >あなたの主張は、Smalltalk-80で関数型的な表現が可能なのは、
>Smalltalk-72の時点でLISP発LOGO経由で
>LISPの関数プログラミングのエッセンスが導入されていたからだと。
その「LISPの関数プログラミングのエッセンス」とは何か?だけど、
まずSmalltalk-72のmapは単純にコレクション系オブジェクトの各要素へ
メッセージを送信するだけで、(doneは無関係だから)関数的だと思う
逆に、手続き的な構文要素は(doneで終わる)repeatだと思うけど、
これも(関数的なmapの)構文糖であると見なすことも可能ではないかと思う
>具体的には、
>>834 的なコードをSmalltalk-72のmapでどう実装するか、....
そのとおりだね
自分が(
>>837 で)「Smalltalkなら関数的作法で書ける」と言ったのだから、
(たとえそれがSmalltalk-72であっても)コードはこちらから示す必要があるだろね
そのコードは、もう少し待って欲しい(Smalltalk-80ならすぐに書けるんだけど....)
あと、Smalltalk-72の実行環境は手元に無いから、おそらく動くであろうと考える
コードしか示せないことを、あらかじめ承知してもらいたい
>>834 全然話の流れと関係ないが、Pythonならこれで良いかと
reverse = lambda x: x[::-1]
>>864 ここでの議論は、ある言語(またはそのプログラミング作法)が
関数型か否か(あるいは関数的か否か)という判定であり、
その判定と環境の有無は無関係だろ
もちろん言語誕生の歴史も判定とは無関係
で、そちらが無理矢理に環境や歴史を絡めたいと考えるのは自由だけど、
絡めるなら絡めるで、論理的に成立する主張をしてくれ、って話だよ
>>865 同一人物であるなら、それで無問題だよ
口調が
>>847 と
>>864 とではまるで違うし、本人であるとも書いていないので、別人だと思っただけ
自分が他人のソースに文句をつける時には、自分もそれに反しないソースを用意しておくし、
それが常識だと思っていたけど、
>>847 はそうじゃなくて、
単に理屈で反論できないからイチャモンを付けたかっただけだったのね、というどーでもいい話
>>866 えーと、
>>862 の一致しない型というのはプログラミング言語のデータ型のことではなく、
数学の集合のことなんだけど.....
話にならないので、論理に加えて集合も勉強しなおしてから出直してくれ、たのむ
873 :
871 :2012/02/22(水) 22:58:59.30
874 :
デフォルトの名無しさん :2012/02/23(木) 00:52:26.77
関数型言語使うのに、 型理論系の知識ってあった方が良いですか?
流れぶった切ってスマン 母校の工業高校ではCとBasicでプログラミング教えてるっぽいんだが、 Haskellみたいな言語で大まかな処理の流れを説明してからCで作らせた方が挫折者が減るんじゃないか?とか考えてて、 有効そうだったら、母校に提案してみようと思うんだが、どうだろう? 上のreverceの例だと、Cで書くならこんな感じのコードになると思うんだが #define SWAP_CHAR( x, y ) {char c; c = x; x = y; y = c;} void reverse(char t[]) { int i,j; for(i = 0, j = strlen(t)-1; i < j; i++, j--) SWAP_CHAR(t[i], t[j]); } Haskellだと同じアルゴリズムで書くなら、こんな感じのコード reverce [] = [] reverce (x:xs) = [last xs] ++ reverce (init xs) ++ [x] Haskell(と言うか、リストと再帰の組み合わせ)だと、リストに対して、線対称の位置にある値を交換して、真ん中まで来たら終了。と言うのが明確に分かるし、 これをヒントにCでreverce書けなかった子にも、書けるようになるんじゃなかろうか
ぱっと見の感想 (1)要素数が奇数だったら落ちる (2)毎回lastとinitするのがクソ遅い (3)Cと比べてHaskellは破壊的代入を使ってない そして一番大事な点は、プログラミング出来ない子にとっては 再帰は難しいってことを忘れてる
Cのreverseの実装が破壊的なのは初心者にmallocを教えるのが難しいというのが大きいと思うがな 手続き型のスタイルで書いてもアロケーションを気にしないでいい言語なら楽だろ function reverse( xs ) { var ret = new Array; for( i in xs )ret[xs.length-i-1] = xs[i]; return ret; }
>>876 寝ぼけてましたね。。。
奇数については
reverce [x] = x
を2行目に追加すれば良いとして、リストで配列向きのアルゴリズム使えば遅いのはしょうがないです
Cのコードで再帰使ってないとおり、どう言う動きのコードを書けば良いかのヒントになりさえすれば良いと考えています
再帰が難しい。。。ですか
確かに、x = x + 1を理解出来ない子も居ますしね。。。
階乗を例にして何とか理解して貰えたら。。。
訂正 x reverce [x] = x o reverce [x] = [x]
>>878 >再帰が難しい。。。ですか
>確かに、x = x + 1を理解出来ない子も居ますしね。。。
x = x + 1 は再帰じゃないよんw
なんとなく、このままいくと
>>878 の母校で
「【アンチ】関数型言語は使えない【玩具】」な高校生が
大量生産されそうなオカン
やっとこさ代入を覚えた子供達が Haskellで x = x + 1 を書いて困惑するわけですね
>>875 の C が読みにくいのは、破壊的なのと、C が文字列を直接扱えないのが原因なので、
関数型かどうかは関係ないよね。というわけで、そこだけ C++ の string 使って書いちゃえ!
(
>>877 とほぼ同じになるはず)
再帰が難しい、と言うより物事の表現方法として再帰を教えてないからなあ。 小学生でも、普段の生活の中で帰納・演繹→再帰を理解するくらいの基礎経験はあるから、これは教える側の問題。
>>884 同感だなあ
再帰なら入れ子になったデータ構造がタマネギの皮を剥くように展開されている様子を
絵やアニメで表現すれば、子供達でも理解しれくれると思う
たとえば手続き型言語ならフローチャートやPADのような図表現があるように、
関数型言語ならヘンダーソン図などがあるのに使わないんだよね
>>880 いえ。。。
それはBasicの授業での話で。。。
そう言う子がいる以上は、再帰が分からない子も居るだろうな、と
>>872 Wikipediaを持ち出した主張への反論の中で
別のフリーの百科事典の記述を提示することが
矛盾だと思うような感性w
LISP言語とLISP環境は型エラーだけど
LISPのmapとst72のmapは型エラーにならないとか、
型付き集合論ならZF系を修論で扱ったが
さすがにこんなトンチンカンな公理系は知らんわw
再帰と言えば、マンデルブロ集合のCG見た時に、これって生命現象そのものじゃね?と思った。 親個体のごく一部が大きく育って子になり、またそれを繰り返す... すれ違いスマン。
888 :
デフォルトの名無しさん :2012/02/23(木) 23:31:33.51
>>875 Haskell版2行目は、
reverce (x:xs) = reverce (xs) ++ [x]
ではあるまいか。それはどうでもよくて、C版が配列(非再帰的構造)に対し、
Haskellがリスト(再帰構造)と、データ構造が異なるなるのが問題。
概念→実装詳細と授業展開するなら、C版もリストにすべし。
>
>>888 reverce (x:xs) = reverce (xs) ++ [x]
は「線対称の位置にある値を交換して、真ん中まで来たら終了」
じゃない
>>888 データ構造の違いは百も承知です
アルゴリズムと言うほど大層で無い手順でも躓く子が居て、そう言う子には、変に図で説明するより、再帰的な表現の方がわかり易いのでは無いか?と思ったのがきっかけで、処理効率とかデータ構造の違いを無視して、アルゴリズムだけを抽出して説明したいのです
そこで、アルゴリズムの可視化にhaskellが使えるのでは無いだろうか?と言うのが、私の考えです
躓く子がいるのは単にあなたの説明が下手なだけでは? ここの書き込みを見るに、わかりやすい説明ができそうな気がしない
>>892 まあ、口下手は否定しません
ただのOBですし、教材作る時間も限られるので、haskellの様なアルゴリズムの可視化に向いてる言語を利用しようと言う魂胆です
有効そうなら、実際に使ってみようかと考えてる訳です
そもそも母校の教員にHaskellを教えるのが無理っぽい
人それぞれの個人的な想い出の範疇の話になるんだろうけど 自分の場合は 関数型言語がえらい流行ったのって もう5年以上前になるんじゃないかな… C++でOS自作したとかいう目の下の黒いプチ有名人が (OS自作ブームは10年前か?) 紫色の勉強する過程をbLogにうpしてたの覚えてるわ Google社のエンジニアリング部門のインフラ言語に 使われてるらしいとか、なんかで読んだことあるけど それ以外で何が開発されたとか 寡聞にして一切聞いたこと無い まだ学習すんの流行ってんの?
簡潔に書けて静的型検査がある言語が使いたい場合 型推論付きの関数型言語くらいしか選択肢が無い
現状では純粋関数型言語のメリットよりはデメリットの方が大きいと思うけどな OCaml系でType Classが入れば個人的にはかなり満足
純粋であることにそんなデメリットってあったっけ
純粋であることというか IOモナドとかを使わずにプログラミングするスタイルが というべきかな? このスレの上の方でも出てるけど グラフ操作とか双方向リストとかシンプルで効率の良い実装の困難なものが結構ある 割り切ってIO使いまくったコードを書くのもそれはそれでありかなと今思った
効率上の必要があるならIOとかST使いまくれば良いと思う STなんてそのための存在だし
STは型注釈がめんどくさいんだよな
902 :
デフォルトの名無しさん :2012/02/25(土) 01:19:42.90
型注釈って、モナドの烙印のこと。 IORefは使ったことあるが、STはない。
903 :
デフォルトの名無しさん :2012/02/25(土) 01:20:51.25
最初の文に?を書き忘れた。
904 :
デフォルトの名無しさん :2012/02/25(土) 01:28:40.83
>>895 関数型言語って流行ものだったのか!?
Perlのように使えて、記述がわかりやすく対話的環境があるものが欲しかった
のだが、SML/NJが実によくできていたので、これを使うことにした。
それこそ、最初は電卓のかわりとして。
関数型は現実的な場面だと金融計算なり、通信用の並列的な処理なりに使われてるじゃないの? 大手のHPじゃソースコードの解析に使ったなんて使用例をみたな。 それでなくとも、今後にゃ統計処理やテキストマイニングが重要になるから、 パーサー書いたり、統計処理での数値計算、並列処理なんかの用途が考えられるし、 そこら辺の動的言語よか、ずっと実用的なんじゃないかなと思っているけど。
906 :
デフォルトの名無しさん :2012/02/25(土) 01:54:07.67
> 統計処理での数値計算、並列処理 これはRがかなり成功してますね。他にも、処理系はあるのでしょうか。
C言語ってアセンブラより難しい。 理由は詳細なコメントを書かない人が多い。 Cなどのコーディングを読む力が強すぎると単なる記号の並びの 本人以外が読み取るのが難しいものを作ってしまう。忘れやすい人には 不向きだ。記憶力が無いと馬鹿にする人も多いが規模が大きくなれば 暗記できる量など誰でも限界はある。 アセンブラが難解だといっている人は、逆アセンブルソースを見て 理解できないという話かと思う。 分かりやすく設計し設計書を残しコーディングすれば問題はない。
スレタイって つまるところ スレ住人には使えない って意味でよろしいか?
もはや誰もスレタイなど気にしていない
>>906 処理系ということならS S-PLUS
あとはStata、SAS、
SPSSとそのオープンな実装PSPP
911 :
868 :2012/02/25(土) 09:29:33.41
>>863 お待たせ、Smalltalk-72によるreverseの実装コードです(アク禁により、カキコ代行を依頼)
to reverse vec
((vec length) = 0 =>
(^ vector 0)
^ (reverse vec[2 to (vec length)]) + vec[1 to 1])
・全体としてSmalltalk-72の構文は、(その後継のSmalltalk-80よりも)LOGOとの類似性が強い
・2行目行末の '=>' および3,4行目行頭の '^' は、それぞれ条件分岐とリターンの意味
本物のAltoマシン上では、特殊キーで入力するアイコン風の特殊記号で表示される
・標準のvectorクラスを使い、Ruby(
>>832 下段)を参考にして実装している
LISP/LOGOのリストに対応する構文は、Smalltalk-72では定義されておらず、vectorを使う
ただし、ドット項に対応するlinkクラスがあり、car/cdr/cons相当のリスト処理も記述できる
いまどき関数型言語を名乗るなら、せめてこれくらいは書けてほしい primes = f [2..] where f (p:xs) = p : [x | x <- f xs, x `mod` p /= 0] ps = takeWhile (< 100) primes ポイントは素数生成アルゴリズムとループ終了条件が分離出来ているところ コードの独立性と再利用性が高まるからね
>>912 Python
from itertools import count, takewhile
def primes():
def f(p, xs): return p, (x for x in xs if x % p)
xs = count(2)
while True:
p, xs = f(xs.next(), xs)
yield p
ps = takewhile(lambda x: x < 100, primes())
>>912 関数型言語LOGOの影響を受け
関数的作法で書けるSmalltalkなら余裕ですよ?
たぶん
916 :
デフォルトの名無しさん :2012/02/25(土) 15:30:35.33
>>912 理解するのに30分かかった。pure functionalはむつかしいのう。
>>914 pythonって遅延評価もっているの?
>>915 Smalltalkは知らないが、これをやるには遅延評価がいる。処理系に組み込み
の遅延評価がなくても、チャンクを書けばできなくはないが、それだったら
命令的に書いたほうがわかりやすい。
遅延評価つーか、イテレータ(ジェネレータ)ですな。
918 :
デフォルトの名無しさん :2012/02/25(土) 16:16:22.99
a b
919 :
デフォルトの名無しさん :2012/02/25(土) 16:19:22.12
で、MLでチャンクを使ったバージョン。すこし準備がいる。 datatype 'a lazylist = NULPO | CONS of 'a * (unit -> 'a lazylist) fun tabulate (f: int -> 'a): 'a lazylist = let fun tabulate' (i:int): 'a lazylist = CONS (f i, fn () => tabulate' (i + 1)) in tabulate' 0 end fun takeWhile (xs: 'a lazylist, cond: 'a -> bool) = case xs of NULPO => nil | CONS (x, f) => if cond x then x :: takeWhile (f(), cond) else nil fun filter (cond: 'a -> bool) (xs: 'a lazylist): 'a lazylist = case xs of NULPO => NULPO | CONS (x, f) => if cond x then CONS (x, fn () => filter cond (f())) else f()
920 :
デフォルトの名無しさん :2012/02/25(土) 16:19:57.14
val primes = let fun f (CONS (p,xs)) = CONS (p, fn () => filter (fn x => x mod p <> 0) (f (xs()) )) in f (tabulate(fn i => i + 2)) end
921 :
デフォルトの名無しさん :2012/02/25(土) 16:27:40.07
ジェネレーターを使っていいならSqueak Smalltalkでも書けなくもない。 | primes | primes := Generator on: [:g | | f xs | f := [:gen | | p | p := gen next. Generator on: [:h | [ | next | ((next := gen next) isDivisibleBy: p) ifFalse: [h yield: next]. ] repeat]]. xs := Generator on: [:h | 2 to: Float infinity do: [:n | h yield: n]]. [g yield: xs peek. xs := f value: xs] repeat]. (1 to: 1000) collect: [:each | primes next]
923 :
デフォルトの名無しさん :2012/02/25(土) 16:57:35.04
filterにバグがあったので訂正。 fun filter (cond: 'a -> bool) (xs: 'a lazylist): 'a lazylist = case xs of NULPO => NULPO | CONS (x, f) => if cond x then CONS (x, fn () => filter cond (f())) else filter cond (f())
>>914 をPython3系列で動かすには
xs.next() を next(xs) に書き換える必要があるね
925 :
デフォルトの名無しさん :2012/02/25(土) 17:04:46.58
もはや難読化ツールだな。
>>922 ジェネレーター使って素数生成と終了条件を分離するだけならこれで十分かとも。
| primeGen |
primeGen := Generator on: [:g |
| primes |
primes := OrderedCollection new.
g yield: (primes add: 2).
2 to: Float infinity do: [:n |
(primes noneSatisfy: [:prime | n isDivisibleBy: prime])
ifTrue: [g yield: (primes add: n)]]].
(1 to: 1000) collect: [:each | primeGen next]
>>928 Smalltalk知らないんだけど、その方法って
ps = takeWhile (< 1100) $ dropWhile (< 1000) primes
のように 1000 <= p < 1100 の範囲の素数が欲しいときに
メモリが無駄にならない?
>>927 そうなのか
上がってたからスレ読んでみたけど
>>912 が何か分からない俺には早すぎますた
>>929 その方法とはどちらでしょう? primeGen の実装? それとも最後の素数の集め方のほう?
前者は算出済み素数を保持するくらいしかメモリは使っていないので、
遅延評価やましてジェネレーターを量産する方法よりは消費は少ないような気がします。
後者は書き方次第ですね。集めてから捨てるとかだと無駄ですが、
欲しい区間だけ集めるようにすれば無駄な領域確保は必要ないと思うので。
>>930 primes = 素数列
2から始まる数列を素数で割って、残った数列の先頭にある数もまた素数であるという、アリストテレスの櫛(くし)(又は篩(ふるい))というアルゴリズムを書いたもの
素数列 数列
(今は空) 2,3,4,5,6,7,8,9,10...
2で割る
素数列 数列
2 3,5,7,9...
3で割る
素数列 数列
2,3 5,7,...
" Squeak Smalltalk (
http://sourceforge.jp/projects/squeak-ja/ ) "
| primeGen p time0 result |
primeGen := Generator on: [:g |
| primes |
primes := OrderedCollection new.
g yield: (primes add: 2).
2 to: Float infinity do: [:n |
(primes noneSatisfy: [:prime | n isDivisibleBy: prime])
ifTrue: [g yield: (primes add: n)]]].
#(0 100 1000 1100 10000 10100) pairsCollect: [:min :max |
gcStats := SmalltalkImage current getVMParameters.
time0 := Time millisecondClockValue.
result := OrderedCollection new.
[ ((p := primeGen next) between: min and: max) ifTrue: [result add: p].
p < max
] whileTrue.
SmalltalkImage current getVMParameters keysAndValuesDo: [:idx :gcVal |
gcVal ifNotNil: [gcStats at: idx put: (gcVal - (gcStats at: idx))]].
time := Time millisecondClockValue - time0.
SmalltalkImage current garbageCollect.
{min->max. time "ms". gcStats second "bytes" . result asArray}
]
"Squeak4.2-ja (CogVM), 1.8 GHz Core i7 =>
{ {0->100 . 0 . 23692 . #(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)} .
{1000->1100 . 1 . 199580 . #(1009 1013 1019 1021 1031 1033 1039 1049 1051 1061 1063 1069 1087 1091 1093 1097)} .
{10000->10100 . 35 . 1667972 . #(10007 10009 10037 10039 10061 10067 10069 10079 10091 10093 10099)}} "
Haskellでswap関数
破壊的な代入が普通には出来ないから、良くも悪くも頭の体操になるな
update 0 a (_:xs) = a:xs
update n a (x:xs) = x:update (n - 1) a xs
swap n m xs = update m (xs!!n) (update n (xs!!m) xs)
こんなブログもあって、swap一つでも楽しめる
Haskell でリストの要素を swap する 9 つの方法
http://jutememo.blogspot.com/2011/04/haskell-swap-9.html
もっと読みやすいソースをどうぞ。
コードなんてもともと読みにくいものだと思えば、どうということはない
櫛とか釣りにも程がある
943 :
デフォルトの名無しさん :2012/02/26(日) 06:02:54.98
>>941 終了判定の分離をあきらめてよければ、より手続き的に書けるだろう。
fun primes' upto = let
fun test p xs = List.all (fn x => p mod x <> 0) xs
fun loop p xs =
if p < upto
then loop (p + 1) (if test p xs then p :: xs else xs)
else xs
in
loop 2 nil
end
ところで、エラトステネスではなかったか。
>>937 何か勘違いしているようだけど、関数型スタイルは
>>912 (Haskell)と
>>920 ,943(SML)だけで、
>>914 (Python)や
>>922 ,928(Smalltalk)は手続き型スタイルだよ
関数型スタイルというのは(副作用を伴わない)宣言的な記述が特徴
でも、
>>914 (Python)はwhile文という手続き型の反復構文が使われているし、
>>922 ,928(Smalltalk)では変数primesへの破壊的代入が使われているから、宣言的とは言えない
どちらもジェネレータ(イテレータ)と呼ばれる手続き型コード化技法の応用になる(
>>917 )
仮に、処理効率を考慮してライブラリ(Pythonのitertoolsモジュール、SmalltalkのGeneratorクラス)の中で
手続き型コードの利用を選ぶことを認めるとしても、ユーザコード内では宣言的に書けるべき
結論としては、「リスト反転(
>>831 )」というお題では分からなかった手続き型と関数型の違いが、
この「エラトステネスの篩(
>>912 )」というお題で(少しだけ)見えてきた、と言えるのかもしれない
>>912 は『プログラミングHaskell』p.160の改悪だろ
primes = sieve [2..]
sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0]
ちょっとした違いだけど分かりやすさも性能も桁違い
まったくもってどうでもいいw
qsortでもあったなそういう話
Haskellってちょっととちくるうとすげー遅いコードになっちゃうのな。 quick sort もシンプルだけど全然クイックじゃないし。 おまけにモナド使って手続き的に書いたほうが速いとかないわ。
>>952 Haskellに限らず、再帰で書けばそんなもん
同じ程度の読みやすいコードなら、コンパイルすればpython/rubyより速いっぽいんだが、私はpythonもrubyも使ったことが無い・・・
>>953 >Haskellに限らず、再帰で書けばそんなもん
ですよね。それがスレタイの本質では?
データ構造の問題。変更可能配列を使うかリストを使うか 再帰で書くかどうかは関係ない
>データ構造の問題。変更可能配列を使うかリストを使うか それがスレタイの本質では?
独立した問題じゃねーよ 破壊的代入を使わなければループを書けないから 必然的に再帰で書くしかないだろ
>>956 破壊的書き換えのできる配列を使えない関数型言語があるなら、
俺もそんなの使いたくない
>>957 配列を書き換えるかどうかの問題、ループ変数を書き換える話はしてない
古典的な再帰とループとは確かに互いに別物だが、今は最適化もあるし、どちらかで悩むのは学習のときぐらいだろ。 スレタイで言うところの実用を考えると、悩むべき所はもっと他にあるぜ。
たぶん遅いのは再帰のせいじゃなくてlazyのせいじゃねーの?
Haskellは遅くない(キリッとか、トイプログラムのベンチマーク見せて力説する信者がいるけどさ、 能力があるプログラマが十分な時間かけてチューニングして書くんだったら アセンブリで書いたほうがずっと速くなるってのw
アセンブリより速いと言われてるのは見たことない
>>958 配列にインデックスアクセスして書き換えるというのは
再帰の引数にインデックスを渡すわけで
実質的に手続き型と言えよう
>>963 関数型言語を使うときに必要に応じて手続き型で書くのは普通のことだよ
関数型言語でも破壊的代入を行えるし、手続き型言語でもクロージャを扱えるからなあ。 今は垣根なんてなく両方のいいとこを取り入れて書くのが普通。
末尾再帰最適化、カリー化、パターンマッチあたりが 関数型言語の特徴と言えば特徴かね
>>960 でもリスト上のmapなんかは正格評価で速くするの面倒くさいじゃん
正格評価だとスタックオーバーフローを認めるか
末尾再帰で書いて最後にreverseするか
変換のコスト払って破壊的操作できるデータ構造(配列など)に変換して
計算するしかないんじゃないの?
とりあえず、C版のreverseとHakell版reverseのコード量比較&速度比較
(Haskell版は普通のリスト向けのアルゴリズムと、配列向けのCと同じアルゴリズム(をリストに対して適用したVer)の2つ作ってみた)
意外なことに、Haskellのreverse2つに速度の差は出なかった
むしろ、メモリ使用量でCのアルゴリズム版の方が省メモリだった
配列(又はリスト)の要素数が6500なのは、このサイトでは要素数7000を超えるとCのコードでランタイムエラー起こすから
(PC上のコマンドラインでは10000でも余裕で動いてるし、Haskellも10000までならかろうじて我慢できる速さ@Core i5 mem:2GB環境)
ぶっちゃけ、Haskellはコード量と速度のバランスは悪いかなとは思うんだが、python/ruby分からんので、そっちの方は誰か頼む
Cのreverse
http://ideone.com/ylwPb Haskellのreverse(よく見るコード版)
http://ideone.com/BkMS5 Haskellのreverse(Cのアルゴリズムをリストに使った版)
http://ideone.com/9fGR3
>>968 比較のやりかたがわけわからん
・HaskellでO(n)のreverseが簡単に書けるのに、よく見るコードと称してなぜO(n^2)のを使うのか
・「配列向けのCと同じアルゴリズム」を使っておきながらなぜHaskellの配列を使わないのか
>>969 Haskellも勉強中なんでね
よければ、Haskellの改良版も頼む
一応、基準としては読みやすさと速さのバランス・・・かな
あいまいでスマン
>>970 reverse のような基本関数を自作する時点で読みやすさは最悪だ。
C はその時点で、他の言語と比較不可能な高い高い壁がある
プログラミングHaskellの後ろに乗ってたreverseの定義はこんなだった
計測したら
>>971 と同じか速い(てか、Cの素直なコードよりわずかに速い)
reverse = foldl (\ x xs -> xs:x) []
http://ideone.com/8hIIw 畳み込み系は足し算とか掛け算以外はイメージつかみにくいので、動作を追ってみた
foldl _ v [] = v
foldl f v (x:xs) = foldl f (f v x) xs
reverse [1,2,3,4,5]
= foldl (\x xs -> xs:x) ((\x xs -> xs:x) [] 1) [2,3,4,5]
= foldl (\x xs -> xs:x) ((\x xs -> xs:x) (1:[]) 2) [3,4,5]
= foldl (\x xs -> xs:x) ((\x xs -> xs:x) (2:(1:[])) 3) [4,5]
= foldl (\x xs -> xs:x) ((\x xs -> xs:x) (3:(2:(1:[]))) 4) [5]
= foldl (\x xs -> xs:x) ((\x xs -> xs:x) (4:(3:(2:(1:[])))) 5) []
= v = ((\x xs -> xs:x) (4:(3:(2:(1:[])))) 5) -- foldl _ v []より
= (5:(4:(3:(2:(1:[])))))
= [5,4,3,2,1]
うーん・・・動作確認した後だと
reverse = foldl (\x ys -> ys:x) []って書いたほうがしっくりくる・・・
>>974 コスパ(コード量/実行速度)なら、今のところHaskellだな・・・
他の言語の方が全体ではコスパ良い言語ありそうだが
いつも思うんだが、そういう比較なら量ではなく 「開発時間」/実行速度 で測るべきではないかと。 コード量で物事を測るのは、行数を金に換算できる時だけでいい。
reverseの時間だけ計らないとダメだろ まぁ順序は変わらんと思うが
>>979 良く見ろ
扱ってるリストのサイズが違う
HaskellがPythonより遅いって結果に 皆さんがっかりですか?
いやこの測定方法だとプログラムの起動時間が支配的だろ 4MBの4byte単位のreverseにそんなかかるわけない 素直なコードでも今時のCPUだったら数百usオーダのはず
いやリストのreverseは死ぬほど遅いよ
>>977 python詳しくないんだけど、
reverse(list(range(1,1000001)))[0]
ここって、1から1000001までのリストを反転して、先頭の要素を表示してるのでは?
結果が
1000000
ってのは、間違った結果じゃない?
間違ってない >>> range(1,10) [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>986 なるほど
でも、なんで+1の数字を指定するの?
何か、紛らわしい
for (int i = 0; i < SIZE; i++)
>>981 別に、破壊的にreverse出来ないのに良く頑張ってるな・・・程度
http://ideone.com/KGg1L この程度なら、変数に実行前の結果を入れておけば済む話だけど、元々、関数型言語は参照透明性が保たれれば、マルチスレッド化しやすいってので注目された訳だし
推測するに、pythonのリストは双方向リストで、reverseはポインタを付け替えるだけで実現してると予想
>>987 理由は色々ありそうだけど、例えば2つの並んだ範囲を書く
(0 <= x <= 99) (100 <= x <= 199)
整数なら良いけど連続値なら(0 <= x <= 99.999...)となってしまう
だから範囲は (0 <= x < 100) (100 <= x < 200) という「以上〜未満」で書いた方が安心確実だよね!
とかそんな感じじゃね
>>990 残念ながら、
>>977 は元のリストには何の副作用もない。
Pythonインタプリタが非破壊的にリバースしている。
>>988 それを言うなら、Haskellだって、[1..10]ってしても、その後ろに空リストが並んでるわけで・・・
javaと言うか、C系列でも、配列の宣言はint a[10]で、indexはa[0]からa[9]の十個じゃない?
Haskellも[1..10]ってしても、index(!!)は[1..10]!!0から、[1..10]!!9までの10個だよ
要素数が10個なのに、11って宣言するのはやっぱり変な気がするなぁ・・・
(まあ、他言語のルールをとやかく言ってもしょうがないんだけど)
995 :
974 :2012/02/28(火) 20:37:56.79
>>981 >>977 のPythonコード
def reverse(x): return x[::-1]
が速いのは、スライスと呼ばれる配列構成子を利用しているから
つまり、x[::-1] が「配列 x の末尾要素から逆順に列挙して得た配列を返す」という意味だから
Cで書くと、以下のようになる
void reverse(int *src, int *dst, int size) { int i; for (i = 0; i < size; i++) dst[(size - 1) - i] = src[i] }
スライス機能はCで実装されているから、Haskellより速いのは、当たり前と言えば当たり前の結果
ただし、RubyでもArrayクラスにreverseメソッドが定義されているから、
たった x.reverse だけでHaskellよりも高速(かつ非破壊的)に実行できるけど、
それをRuby信者が
>>977 ,981のように「自慢げに語る」ことは見たことも聞いたことも無いなwww
>>981 >>977 のPythonコード
def reverse(x): return x[::-1]
が速いのは、スライスと呼ばれる配列構成子を利用しているから
つまり、x[::-1] が「配列 x の末尾要素から逆順に列挙して得た配列を返す」という意味だから
Cで書くと、以下のようになる
void reverse(int *src, int *dst, int size) { int i; for (i = 0; i < size; i++) dst[(size - 1) - i] = src[i] }
スライス機能はCで実装されているから、Haskellより速いのは、当たり前と言えば当たり前の結果
ただし、RubyでもArrayクラスにreverseメソッドが定義されているから、
たった x.reverse だけでHaskellよりも高速(かつ非破壊的)に実行できるけど、
それをRuby信者が
>>977 ,981のように「自慢げに語る」ことは見たことも聞いたことも無いなwww
>>994 Pythonのrangeや
>>988 はindex、配列の宣言はsize
indexとsizeを混同してはいけない
begin <= 有効index < begin + size (= end)
>int a[10]で、indexはa[0]からa[9]の
普通にfor文書いたら(0<=i<10)になるだろ?
for(int i=0; i<10; i++){...}
1000 :
デフォルトの名無しさん :2012/02/28(火) 21:04:55.07
性玩具
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。