関数型プログラミング言語Haskell Part34 (692レス)
1-

リロード規制です。10分ほどで解除するので、他のブラウザへ避難してください。
667: デフォルトの名無しさん [] 2025/03/19(水) 20:52:16.86 ID:S6mpqhEQ(2/2) AAS
誤爆スマソ。懐メロチャンネルと間違えた
668
(3): デフォルトの名無しさん [] 2025/10/08(水) 08:47:56.03 ID:66xUgFQM(1/2) AAS
int* map(int (*f)(const int), const int* array, const int n){
  int* p = malloc(sizeof(int) * n);
  for(int i = 0; i < n; i++) p[i] = f(array[i]);
  return p;
}

ふむ、メモリ管理が必要な言語が(見かけ上)副作用のない関数を作ろうとしたら配列を返す関数の時点で関数を使った後は必ずメモリの開放が必要になるのか。
開放が必要だから、参照を持つためにポインタへの保存が必須なので、関数の連続適用(関数合成)は絶望的。

これじゃ、GCやRustみたいな仕組みが必要になるわけだ。
669: デフォルトの名無しさん [sage] 2025/10/08(水) 10:40:05.18 ID:qRy2t+J8(1) AAS
Cで副作用はいうてらんないね。マルチスレッド、再入可能にするところまで出来れば上出来
670
(1): デフォルトの名無しさん [sage] 2025/10/08(水) 13:07:06.38 ID:4LSFWHe4(1) AAS
>>668
30点の理解
671
(2): デフォルトの名無しさん [sage] 2025/10/08(水) 14:05:41.01 ID:JTvRYaZp(1) AAS
GC言語はGC使ってる時点で副作用あるやんw
メモリ管理他人任せにしてるだけだ
672: デフォルトの名無しさん [sage] 2025/10/08(水) 17:42:33.77 ID:1ctt2fBW(1) AAS
>>671
−30点
673
(1): デフォルトの名無しさん [] 2025/10/08(水) 18:32:01.08 ID:66xUgFQM(2/2) AAS
>>670
100点満点のご高説をどうぞ。
長文になっても良し。

>>671
実は純粋関数型言語の定義は「副作用も含めて参照透明性が破れていない」なのです。(Wiki調べ)
print関数やgetLine関数はどう見ても副作用有るでしょう?
でも、モナドのお陰で参照透明性は破れてないんですよ。
674: デフォルトの名無しさん [sage] 2025/10/08(水) 18:44:02.95 ID:N7mcxj5n(1) AAS
副作用は隔離スレへ
675: デフォルトの名無しさん [sage] 2025/10/08(水) 18:45:31.77 ID:HFQA1hQ+(1) AAS
なるほどモナドと書き込めばこのスレで副作用の話もできるのですね
676
(1): デフォルトの名無しさん [sage] 2025/10/08(水) 23:41:30.24 ID:jkiZK6Mq(1) AAS
>>673
ゴールがわからないので100点のご高説は無理だが30点の理由は説明しといてあげる

C言語という特定の言語実装における制約がメモリ管理が必要な言語全般に対しても当てはまると考えてるのが根本的な間違い

>配列を返す関数の時点で関数を使った後は必ずメモリの開放が必要になるのか。
>>668のコードで(明示的な)メモリ解放が必要になるのはヒープに動的にメモリをアロケートしたからであって配列を返すからではない

C言語では配列がfirst classではないので配列をそのまま返すことは不可能
C言語でも構造体ならfirst classなので配列という概念を表現した構造体を作って静的配列を返すようにすれば(明示的な)メモリ開放は不要
C言語にはないがジェネリック等の抽象化機構を備えた言語であれば静的配列を使って任意長の配列に対するmap関数も書ける

>開放が必要だから、参照を持つためにポインタへの保存が必須
動的にアロケートするものは実行時になるまで必要なメモリサイズがわからないから言語に関係なくポインタ的なものでしか表現しようがない
動的にアロケートしたものだからポインタが必須、ヒープに動的にアロケートしたものだから後で(明示的な)開放が必要なのであって、開放が必要だからポインタへの保存が必須という因果関係ではない
677
(1): デフォルトの名無しさん [] 2025/10/09(木) 02:23:13.64 ID:j1OYGPg+(1/5) AAS
>>676
確かにメモリ管理が必要な手続き型言語全般というのは広げすぎたかもしれない。
静的な配列を関数内で作ってポインタを返す形で作ると関数を抜ける際に配列の寿命が尽きる。
(通常、それを避けるために結果を格納するためのポインタを引数で渡す)

C言語で関数型言語のmap関数みたいな配列を返す関数が作れるか?と考えると動的に作って、使い終わったら解放する形になるのかなと。
ここへの書き込みが長すぎると怒られたので削除したが、構造体で包むという案も考えた。
値渡しだからコピーコストがかさむ。
参照渡しだと生の配列と同じ寿命の問題に突き当たる。
678
(2): デフォルトの名無しさん [sage] 2025/10/09(木) 10:26:59.37 ID:DbxsJTmB(1) AAS
>>677
>値渡しだからコピーコストがかさむ。
コンパイラの最適化で不必要なコピーは消える
C言語でもそういうことは当たり前にやってる
679: デフォルトの名無しさん [sage] 2025/10/09(木) 11:59:08.62 ID:4MZdWW58(1) AAS
仕様化されてるっけ
コンパイラの実装次第だと怪しい
680: デフォルトの名無しさん [sage] 2025/10/09(木) 17:36:59.11 ID:jE8FE7Nk(1) AAS
Cに何を求めてんだよw
681: デフォルトの名無しさん [sage] 2025/10/09(木) 17:53:09.88 ID:N3YUsGEr(1/2) AAS
OS開発ですね。メモリも割り込みも何でも見えてしまい、扱わないといけません
682
(1): デフォルトの名無しさん [] 2025/10/09(木) 18:19:20.69 ID:j1OYGPg+(2/5) AAS
>>678
にゃんと!?
それを押してもいざ実装してみたら
構造体で配列を包む場合、あらかじめ配列の長さを決めないといけなかった。

struct {
    int array[1024];
    int size;
}typedef Array;

この1024とかも余分な分は最適化で無くなるっていうなら10万位要素があっても大丈夫なように1GB位(見かけ上)確保したいが、そうでないなら大体の場合、無駄な領域を確保してることになる。
683
(1): デフォルトの名無しさん [] 2025/10/09(木) 18:28:04.54 ID:j1OYGPg+(3/5) AAS
>>678
ん、まてよ?
最適化で不要なコピーは消えるって言っても、関数プログラミングのmap関数と同じ動きなら、参照元の値は変わったらダメなので参照渡しされたら困るんだが、どんな最適化でコピー(値渡し)で無く、かつ参照渡しでもない状態ってどんな状態?
684
(1): デフォルトの名無しさん [sage] 2025/10/09(木) 19:31:35.47 ID:XykzCJ/G(1) AAS
Haskellは遅延評価だからmapが配列を返してると言えるかあやしい

一般的な関数型言語だと末尾再帰で不必要になる値を再利用(上書き)する
あと値が変更されない(immutable)なら参照渡しで共有しても問題ないし
共有するためにimmutableにすると言っても過言ではない
685: デフォルトの名無しさん [] 2025/10/09(木) 19:50:16.02 ID:j1OYGPg+(4/5) AAS
>>684
うん、遅延評価だから基本参照を返してるはず。バード本参照
(なので>>668を書いてみたわけで)

immutableなら

a = [1..4]
b = map (+1) [1..4]
print a
print b

とうコードで

output:
[0,1,2,3,4]
[1,2,3,4,5]

になるはず。
Cで参照を共有すると

[1,2,3,4,5]
[1,2,3,4,5]

という困った表示になってしまう。
というかHaskellでも生のリスト[0..4]とmap (+1) [0..4]は参照を共有してない。
共有してるのは[0..4]だけ。
(むしろ共有してないからこそ「富豪プログラミング」とか言われる)
686: デフォルトの名無しさん [] 2025/10/09(木) 20:01:16.79 ID:j1OYGPg+(5/5) AAS
言ってみればHaskellは新しい参照をどんどん生み出して、不要になった参照はガンガンGCする。
Cはそういうプログラミングには(当たり前だが)向かないし、当たり前にCの方が効率は良い。
人間が書くコードはHaskellみたく数学に近いほど短くなる。
どっちが良いとかじゃなく、何を優先するかという話。
(なのだなぁと、Cでmap関数もどきを書いて再確認した)
687: デフォルトの名無しさん [sage] 2025/10/09(木) 20:33:26.39 ID:N3YUsGEr(2/2) AAS
ループ書こうぜ
688
(1): デフォルトの名無しさん [sage] 2025/10/09(木) 21:58:50.95 ID:HS++2zZ0(1) AAS
>>682
「ジェネリック等の抽象化機構を備えた言語であれば〜」のところ全然理解してなかったのな

>>683
言語の仕様上は値渡しだけど実際にわざわざコピーして渡す必要がない状況ならコンパイラが最適化してコピーしないマシンコード(コピーして渡すのと同じ結果になるマシンコード)を生成するという話
異なるレイヤーを混同してることに気づいてくれ

あとHaskellのリストは配列じゃないよ
689
(1): デフォルトの名無しさん [] 2025/10/10(金) 05:32:34.82 ID:WzZmvOuY(1) AAS
Haskellを勉強したけど何に使えばいいのか分からない
関数型プログラミングで難しい割に、速度が出ないことがわかっているやっぱり速度は正義だろ
690: デフォルトの名無しさん [] 2025/10/10(金) 07:17:31.85 ID:G/tXieG5(1/2) AAS
>>688
ジェネリックはそのうちC++なりJavaなりで試すけど、まだ試してもいないので…。

最適化の方はもうちょい具体的に教えて欲しいかも。
x = 2 * 100を x = 200にするみたいなのは知ってるけど、あんま詳しくない。
691: デフォルトの名無しさん [] 2025/10/10(金) 07:21:42.77 ID:G/tXieG5(2/2) AAS
>>689
今のHaskellは(中の人がMSに勤め始めてから)C#並みに速くなってるけど、GUIライブラリとか軒並み遅い時代に開発が止まってる…。
しいて言えばYesod使ってWebアプリかな?
Mac(Appleシリコン)版があるからiOSアプリのロジック部分とかも行けそう。
1-
あと 1 レスあります
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.017s