関数型プログラミング言語Haskell Part32
レス数が1000を超えています。これ以上書き込みはできません。
関数型プログラミング言語 Haskell について語るスレです。
haskell.org (公式サイト)
https://www.haskell.org/
日本Haskellユーザーグループ
https://haskell.jp/
前スレ
関数型プログラミング言語Haskell Part31
https://mevius.5ch.net/test/read.cgi/tech/1506447188/ 手続き型でゴリゴリやってきた人にとって関数型は
マラソンの選手に、匍匐前進と水泳で近道するよう強制しているかのようです >>4
手前味噌ですが、Haskell入門以前と言う電子書籍をAmazonでご購入下さい。
まさに貴方のような方に関数脳を作ってもらうための本です^^ 初心者がHaskellでオンライン問題集みたいなの解いてんだけど
Haskellでやるとこういうの楽しくてええな CPS書き換えドリル
次の英文を○○構文を用いて同じ意味の英文に書き換えなさい的な haskell紹介してるブログとか色々あるけどどこも肝心要のところがすっぽり抜けててイライラするな・・
例えば
fact 0 = 1
fact n = n * fact(n - 1)
これ無限ループになっちゃって終わらないでしょ終端条件も書いてないし。
fact 3を展開すると
3 * ( 2 * ( 1 * ( 1 * ………
0を入力すれば1になるってことはこの先ずーっと1が繰り返されるだけだし。
同じ値が2度続いたら処理を止めるとか変な仕組みでも入ってるのかねー >>9
>無限ループになっちゃって終わらないでしょ終端条件も書いてないし。
いえいえ、終端条件が
>fact 0 = 1
です、n ∈ N たる n からはじまって 0 で終わる、と読みます
fact 3 = 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0
= 3 * 2 * 1 * 1
で止まります. >>9
恥ずかしいぞ
>fact 0 = 1
で、これ以上再帰してないじゃん >>12
それじゃ納得できないんだけども
終わるから大丈夫仕様ですってもやっとするから
>>9で書いたように1が無限に続いちゃうと思うんだけどな
0が入力されたら1を返すってことだから
1 - 1でまた繰り返しちゃうよね
そもそもどの値が来たら終わるか全く記述がないよね
そういうところも納得できないっていうかおかしい >>13
>>11 が説明してくれたとおりなのだけど、納得できない? >>14
あの説明で納得するようならここ来てないから
あれだとブログの説明と何も変わらない
まさか1かtrueを返したら問答無用で終わる仕様だったりするのかねー >>13
ああ 言っている意味は分かったけど
続かねーぞ よく考えてみ 恥ずかしい思いするだろうけど
っていうか、>>11のひとが書いてるじゃん
fact 1 = 1 * fact 0
= 1 * 1 で終了だろ
これ納得できないとしたら、別のところで引っかかっている
パターンマッチを理解していないとか >>15
バカで思い込みが激しいって最悪だぞ?どっちかにしろ。 >>16
それじゃ終わらない
終了条件が書いていないから
なんどもいうように * 1がずーっと続くようにしか見えない
だからこの例題見たときにイライラしてたんだよね
前提となってる仕様があるけど説明省いたとかそれ系かなと >>13
では逆に質問しましょうか、そこから両者が部分的にでも合意できるポイントを探ることにしましょう
>>9
>fact 0 = 1
>fact n = n * fact(n - 1)
これをあなたはどのように解釈したかを、もう少し詳しめに記述していただくことは可能でしょうか、私の記述は今は >>13 が精一杯ですが、あなたの返答をみて改善できる点はないか検討したいと思います >>15
ほとんど同じ説明だが…
関数の定義が
fact 0 = 1
fact n = n * fact(n - 1)
となっている。
このとき、左辺が右辺に置き換えられる (簡約という)
つまり fact 3 は 3 * fact 2 に置き換えられる
そして fact 2 は 2 * fact 1 に置き換えられる
そして fact 1 は 1 * fact 0 に置き換えられる
ひとつめの関数の定義により、fact 0 は 1 に置き換えられるので
置き換えはここでとまる
以上をまとめると
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0
= 3 * 2 * 1 * 1
= 6 >>15
fact 0で問答無用で終わる仕組みですが。。。
>>11 以上にやさしい説明はないと思われ。
普通の言語(ここで >>18
終了条件は
>fact 0 = 1
です。関数 fact の引数が 0 なら、1 を関数の値として返し、fact の求値作業は終了します。
fact への入力が 1 でないならば
>fact n = n * fact(n - 1)
の定義をつかって、最初の入力 n よりも小さい値 n - 1 (< n) を使った関数定義がつかえるように変換します >>19
理解したのは>>9の通りで
仮定として1かtrueを返したら再帰は止まる仕様になってると推測してる
>>20
だからfact(1)で無限に続いちゃうよね
1 - 1で fact 0をevalしてまたfact(1)になる
そこで終了条件が必要だけど何にも書いてないから記述通りならずーっと続く
としか見えないんだよね いやだから
fact 1 で1が出てくる でまた、fact 1になって永遠に続くとかの勝手な思い込みでしょ
あるいは、
fact 0 =1 になるから、また fact 1 -1 になると思ってるとか
だから、永遠に1が続くと勘違いしちゃっている >>22
ということはやっぱり1を返したら必ず再帰は止まる仕様であってるのかな?
だったらすっきりするんだけども >>23
>1 - 1で fact 0をevalしてまたfact(1)になる
ならねーよ そこが恥ずかしいところだ 途中で。。。
まあいい。
Pythonでも再帰出来る。
特別な話じゃない。
def fact(n):
if n == 0:
return 1
else:
return (n * fact(n - 1)) >>23
>>>20
>だからfact(1)で無限に続いちゃうよね
>1 - 1で fact 0をevalしてまたfact(1)になる
>そこで終了条件が必要だけど何にも書いてないから記述通りならずーっと続く
そうはならない
fact 1 = 1 * fact 0
に簡約される
そして
fact 0 = 1 であって
fact 0 = 0 * fact(0 - 1) とは絶対にならないからここで終わる
高校数学がわかるなら、漸化式と同じだと思えばよい >>23
>1 - 1で fact 0をevalしてまたfact(1)になる
>fact 0 = 1
というのは、関数 fact のうち fact(0) (引数が 0) のときの値は 1 である、と確定的な記述をしています。ここで答えが決まったので、さらに答えを求めるための関数適用作業には入りません、それはそういう意味です
どうして eval したあと fact(1) になる、と判断したのでしょうか?
fact(0) = 1 の 1 というのは fact() の値であって、fact の引数ではなく、また fact の引数になりうる記述は 「fact 0 = 1」という記述の中には見つからないのですが
>fact n = n * fact (n - 1)
この記述のなかには、たとえば 引数が 7 だとすると「 fact 8 を fact 7 の値をつかって表現する」ということですから、fact 8 を eval する「途中で」 fact 7 を eval しようとする、ということは書かれています >>25
「1 を返したら」とまるのではなく
fact 0 = 1
と fact の求値が、この行で確定しているから、止まるのです。
fact 0 = 100
という定義であっても、とまりますよ >>28
いやいやfact(1)の評価は0なんだし
fact 0の定義があるからまた1
どう考えても続くんだよね
そもそも再起から脱出するためのコードがどこにもないから怪しいとも踏んでる
何か前提となってる仕様がありそうだ >>29
やっぱりそうなんだ
そういう重要なことは早めに説明書きしといてくれないと大混乱だわ
まースッキリしたありがと
そういう仕様なら色々めんどくさいな・・・ >>33
>いやいやfact(1)の評価は0なんだし
違う
どこにそんなことが書かれている? >>33
>いやいやfact(1)の評価は0なんだし
ここが違っています。
fact(1) の評価は 1 * fact(0) であって、 0 じゃないです
fact(0) の値が具体的になにかは、fact(0) を意識しはじめた時点では分からないのですよ >>33
おもろいな だんだんネタに思えてきた
fact nの定義をよく見ろ
fact 0 = 1 で再帰していないじゃん ここで止まるだろ 普通に考えれば
他の言語も一緒だろ ただそれをパターンマッチでやってるだけ >>34
えーと、すまん、「どんな場合でも」再帰は1を返したら終了すると考えているのなら
それは大間違いだ >>33
fact 1の評価は1 * fact 0
fact 0のみが再帰してない。(基底部)
再帰は再帰部と基底部が必ず最低1個ずつ存在する。 >>23
>>>19
>理解したのは>>9の通りで
>仮定として1かtrueを返したら再帰は止まる仕様になってると推測してる
この推測が間違っているので、いったん忘れて素直にプログラムを読んでみよう >>35
教えてもらったからもう大丈夫だよ
1で再起が止まる仕様なら納得だし
>>36
fact(1)を入力したら 1-1を評価するから fact 0
特に問題ないよ
1で止まる仕様らしいからそれを前提にコード考えないといかんのか・・
ややこしいことになるねこれ >>42
>>29 や >>31 でお墨付きを与えたのが間違いだった
君はまだ理解できていない (断言) >>39
どーゆーこと
もうそれで覚えちゃったんだけども・・ >>42
>1で再起が止まる仕様なら納得だし
理解が不十分じゃないかと危惧します、その台詞「1 で再起がとまる」という言葉ですが、「何が」 1 で再起が止まる、と考えているのですか?
あなたの発言は、いちいち「何が」「どうだ」の「何が」が欠けているので不安です >>44
覚える、という言葉はこういうときに使うものではないと思いますよ もういちど繰り返すが、
>>41 に書いたように
「仮定として1かtrueを返したら再帰は止まる仕様になってると推測している」
が大間違いだ >>45
それだと>>9の通りで揺らがない
>>46
この記述だと無限に *1が続くわけだから
なにか終了条件が必要なわけで
1を返したら再帰が止まる仕様ならなるほど納得 >>42
>fact(1)を入力したら 1-1を評価する
どうしてそう考えたのですか?そのような記述がどこに書かれていたのか説明いただけませんか? >>50
> この記述だと無限に *1が続くわけだから
何で?続かないが。ちゃんと読め。 >>48
大混乱してきた
1で再帰は必ず止まるんでないならさらにわからなくなるんだけども >>51
わかるじゃん fact 0で1が出てきたら、また、勝手に再帰させて
fact 1に戻っちゃう 勝手に脳内変換させちゃってる >>51
fact(1)はfact(n-1)によってfact(0)になるよね
実は式自体が予想外の評価するってことなのかな?
いやまさかね・・ >>50
>この記述だと無限に *1が続くわけだから
あなたの理解になにが足りないのかがわかるような気がしてきました。
「fact の引数が 1 である」と「fact の求値が 1 である」とを区別していないようですね
この二つは厳然として異なります
fact 0 = 1
は、fact(0) の「求値が」1 である、といっているのです
fact n = n * fact (n - 1)
は、たとえば
fact 8 = 8 * fact 7
fact 7 = 7 * fact 6
fact 6 = 6 * fact 5
fact 5 = 5 * fact 4
fact 4 = 4 * fact 3
fact 3 = 3 * fact 2
fact 2 = 2 * fact 1
という記述を纏めて表現しているのであり、これは fact n の「求値」は fact (n - 1) という、もともとの引数 n とは違う n - 1 という引数を使った fact の求値で定義しているのです もしかすると、だけど
fact 0 = 1
を実行した直後に
fact 1 = 1 * fact 0
が続くと考えている?
もうしそうだとしたらそこが間違いで
fact 0 = 1
fact n = n * fact(n - 1)
はそのどちらかしか実行されない >>53
>1で再帰は必ず止まるんでない
「何が」 1 で再帰が止まる、と考えているのですか?
「何が」の部分を答えてください >>54
>fact 0で1が出てきたら、
何が 1 となるのか、そこをはっきり書いてください、「出てきたら」っていいますが、「何が」 1 と出てきたら、なんでしょうか?
>また、勝手に再帰させて
何が 1 となるのか、0 となるのか、そこをはっきりさせないことには、それ以降の思考は不可能ですよ、あなたには「また勝手に再帰させて」とかいうことを考える段階ではありません >>56
ごめん意味不明わからん
>>57
もちろんそのように考えてる
fact 0 = 1の結果はすぐ反映されるんじゃないの? >>59
いや 俺は本人じゃないから
あくまでも、彼の脳内を勝手に想像しただけ 1がつづくケースを考えただけ
そのものでは無いかもしれないけど、どちらにしようが似たようなケースでしょ >>60
ああ、良かった
>fact 0 = 1の結果はすぐ反映されるんじゃないの?
そうだよ。そして fact 0 は 1 を返すから、もう再帰呼出しは起こらないよね?
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0
= 3 * 2 * 1 * 1
= 6 >>63
いやいや終了条件が何も書かれてないから結局は続くよ
どのみちfact 0が1となるならまたfact(1-1)でfact(0)でしょ
間違ってないはずなんだけど何か使ってる人には常識的なお約束事とかあるのかな >>60
>fact 0 = 1の結果はすぐ反映されるんじゃないの?
ようするにそこでとまる
数学の階乗だから fact nの引数は再帰する度に-1される。
どこかで、factの引数が0になったら、それ以上は再帰しない
難しい話じゃないし、他の言語で再帰理解していたら、分かるはず
自分で落ち着いて考えてごらん >>65
いやただのカウンターだったとしても止まらないし
やっぱりおかしいとは思う
何か前提がありそうな気はする >>64
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0 -- fact 0が・・
= 3 * 2 * 1 * 1 -- 1になる。factもうないのにここから何が続くの?
= 6 >どのみちfact 0が1となるならまたfact(1-1)でfact(0)でしょ
fact 1 = 1 * fact (1-1) = 1 * fact 0
となるけど、これは fact 1 の時の処理だね
fact 0 の場合は 1 を返すだけだから、fact(1-1) という処理はもう出てこないよ
今の話は
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0
= 3 * 2 * 1 * 1
= 6
のうち
3 * 2 * 1 * fact 0
が
3 * 2 * 1 * 1
に変化するところだよ >>66
だとすると文法自体理解していない あるいは関数自体
もっと、詳しく書くと
>どのみちfact 0が1となるならまたfact(1-1)でfact(0)でしょ
定義を見てごらん
fact 0 = 1 でこれは、=の右にfactが無いからこれで再帰はしないで、ここで終了
fact n = n * fact n-1 で=の右にfactがあるから再帰する >>67
= 3 * 2 * 1 * 1
= 3 * 2 * 1 * 1 * fact( 1 - 1 )
= 3 * 2 * 1 * 1 * 1 * fact ( 1 - 1)
どこまでも続くじゃない・・ >>70
中学校の数学でそうはならないってことは習うから、学校の数学でそこまで勉強してからプログラミングに手を出しても遅くないのでは? >>69
fact 0 = 1で終了するというのが納得いってない
もしそうであれば1を返せば再帰は終了すると仮定したんだ
そもそもfact 0 = 1ってマクロ定義みたいなもんだし
直ちに評価されて式に代入されるよね >>73
他の言語で再帰ってのは理解しているの?
fact 0 = 1で=の右にfactが無いから、再帰は終了 だから、終了条件は書かれている。
もしこれが理解できないのなら、関数定義とか、パターンマッチとかもっと基本的なことに
戻らないと理解できないと思う >>72
プログラミング言語は数学じゃないから
再帰から脱出するならそのためのコードは絶対必要なはずなんだ
それがないってことは仕掛けがあるはずで
その仮定が1を返せば再帰から脱出できるという考え
でも違うらしいから大混乱してる >>73
fact 0 = 1
で「終了する」というのが間違い
fact 0 = 1
では、fact 0 が 1を返す(正確に言うと1に簡約する)
ということしか定義していない
ただ、もうfact関数を呼び出していないので、再帰呼出しはここで止まる
そして fact 0 = 1 がマクロ定義ということも勘違いなので忘れよう
>>67 が解説してくれた
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0 -- fact 0が・・
= 3 * 2 * 1 * 1 -- 1になる。factもうないのにここから何が続くの?
= 6 >>74
Cで再帰させるなら終了条件にヒットしたらフラグたててreturnで戻ってく
関数定義の仕方ならサッと見たけど特に疑問はなかったよ
パターンマッチっていってもマクロ定義みたいなもんだし特にどうということも >>75
上に書いたけど、漸化式は理解している?
同じ書き方をします
Haskellは数学を基盤としているので、数学的な記述方法でプログラムが書けます
「再帰から脱出するならそのためのコードは絶対必要なはずなんだ」とあるけど、
もう書かれているよ
fact 0 = 1 って >>76
いやだから・・
fact 0は1なんだからその次はfact(1)になるでしょ
何も間違ってないと思うんだけど。 >fact 0は1なんだからその次はfact(1)になるでしょ
その次はもうないよ >>78
それは終了条件じゃないよね
何が正解なのかさらに混乱して来た >>81
君の言い方に合わせると「終了条件」と考えてよい
正しく説明すると
>>40 になる >>42
1で止まる仕様と言うか。。。
掛け算だから1を返すだけ(掛けても変わらない数)で、足し算なら0を返すよ。
sum1toN 0 = 0
sum1toN n = n + sum1toN (n - 1) >>81
終了条件だよ。
>>27のPythonコードで言うと
if n == 0:
return 1
の部分と同じだよ。 >>83
だから・・
fact 0は1なんだから続くじゃない?
延々と再帰するようにしか見えない この人の脳内だと、
fact 0 = 1
が
fact 0 = fact 1
になってるんじゃないだろうか >>85
PythonやJavaは知らないのでなんとも この人 77で書いてるけど、文法まともに読んでないんだよ
Haskell 文法自体は一見綺麗で簡単そうに見えるけど
実際には、理解するのが非常に難しい(今回の再帰のとこじゃないんだけど)
適当に文法流し読みして理解しようとするのが 間違っている
もっとも、階乗の再帰は、他の人の説明で理解できるだろうと思うが >>86
fact 0は1なんだから、
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0 -- fact 0が・・
= 3 * 2 * 1 * 1 -- 1になる。factもうないのにここから何が続くの?
= 6
はい!ここで一旦休憩!君に問題。
3 * 2 * 1 * 1はいくつだ? うーん、C言語だと
int fact(int n)
{
if (n == 0) return 1;
else return n * fact (n - 1);
}
と書くのと同じなんだけどねえ >>90
だから
=3 * 2 * 1 * 1 * fact(1-1)
=3 * 2 * 1 * 1 * 1*fact(1-1)
=3 * 2 * 1 * 1 * 1*1*fact(1-1)
という具合にいつまでもfactは続くよ
だから色々納得いかないことあるんだけど >>92
この1行目はどこから出てきたの?
=3 * 2 * 1 * 1 * fact(1-1)
この辺を脳内でテキトーに処理してるからわからないんだよ
fact 3
のところから地道に書きながら置き換えてみな >>94
それで地道にやったら >>9になったよ
あれ以外どうしろと・・ >>92
算数のテストで
3 * 2 * 1 * 1は?って問題に、
3 * 2 * 1 * 1 * fact(1-1)って答えるの?
それは算数でも数学でもプログラミング言語でも間違いだよ。
算数でも数学でもプログラミング言語でも答えは6だよ。 >>95
そうなのか。C言語はやったことがあるようだけど
>>91 は理解できてる? >>96
そこはどうでもいいところだから書かなかった >>95
ああ、>>9 みたいに一気に展開するのではなくて、
fact 3 =
のところからひとつずつ地道に置き換えてみた?
もしやってないなら、今すぐやってみよう >>97
あれでいいんだけど似たような制御構造がないよね
haskellのコードは全く別物に見える >>95
左辺から右辺に書き換えるって分かってる? >>99
=3 * 2 * 1 * 1
=3 * 2 * 1 * 1 * 1
=3 * 2 * 1 * 1 * 1 * 1
・・・
やっぱり変わんないよ?
何かやってる人には常識だからあえて書いていないとかのお約束ごととかある言語なんじゃないかなぁ・・
パッと見た感じそんなに難しい言語には見えないけど内容に納得できない >>98
どうでもよくないよ。正しい流れは、
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0
= 3 * 2 * 1 * 1
= 6
なのに、>>92によるとあなたは、
fact 3
= 3 * fact 2
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact 0
= 3 * 2 * 1 * 1
= 3 * 2 * 1 * 1 * fact(1-1)
= 3 * 2 * 1 * 1 * 1 * fact(1-1)
= 3 * 2 * 1 * 1 * 1 * 1 * fact(1-1)
であるという。
正しい答え6にたどり着かない原因はあなたが
3 * 2 * 1 * 1
= 3 * 2 * 1 * 1 * fact(1-1)
と変形(?)してしまっているところなのは明らか。 >>64
>またfact(1-1)
どうしてそのように推測したのですか?その 1 - 1 ってどこから誘導したのですか? >>79
>fact 0は1なんだからその次はfact(1)になるでしょ
ちがいますよ。なんども言っていますが「fact 0 は 1 」、っていう言葉が不正確ですね、fact 0 の「何が」 1 なんでしょうか? >>104
fact 0 = 1とか定義されちゃってるから変形もなにもあの形にしかならんでしょう
>>105
fact 0の結果が1だからそれはすぐ反映されるので >>86
>fact 0は1なんだから続くじゃない?
fact 0 の「何が」 1 なんですか?そこが他の者と違っている点かと思います >>92
3 * 2 * 1 * 1 * fact(1-1)
その 1 - 1 はどういう理由で 1 - 1 と書いたのですか? >>107
不正確と言われても他に言いようがないし Cでこんな感じに書いてあげれば分かるのだろうか。
int fact(int n) {
switch(n) {
case 0: return 1; // fib 0 = 1
default: return n * fact(n-1); // fib n = n * fact (n-1)
}
} あっとボケた。>>112のfibはfactの間違い >>110
直前の結果が1なのでfact(n-1)に与えられてfact(1-1)
特に問題ないはずだけどもこれだけなら >>111
あなたは 「fact 0 が 1 」といっていますが、我々は「fact 0 の値が 1」と「fact の引数が 1」とを別のものとして区別しているのです
あなたは区別していますか?あるいは「fact 0 が 1」というけれども fact 0 の何が 1 なんですか? >>114
>直前の結果が1なので
ここはOK
>fact(n-1)に与えられてfact(1-1)
ここが間違い。与えられるfact(n-1)がもう存在しない >>114
結果は結果、引数は引数です
結果を引数に入れたり、引数を結果にいれたりしていないのですよ >>112
なっ
まさかそういう意味なの?
fact 0 = 1
fact n = n * fact(n - 1)
のどちらかしか評価されないとか見ただけじゃわからないって!!
あーそういうことかー >>108
> fact 0 = 1とか定義されちゃってるから変形もなにもあの形にしかならんでしょう
いいえその形には絶対になりません。
「fact 0 = 1とか定義されちゃってるから」
= 3 * 2 * 1 * fact 0
は
= 3 * 2 * 1 * 1
になります。うん、これはいい。次。
「fact 0 = 1とか定義されちゃってるから」
= 3 * 2 * 1 * 1
は
= 3 * 2 * 1 * 1 * fact(1-1)
になります?いいえ、なりません。勝手に足した「 * fact(1-1)」どっから出てきたんだ。
3 * 2 * 1 * 1は6です。 理解できたようで良かったけど、結局は
>>57 がわかってなかったということだなあ これは説明書きに書いておいて欲しかったなー
これじゃわかりようがないわ >>118
よかったね。君へのレスで「パターンマッチ」を検索してごらん >>118
そこでしたか!
うーん、それは見抜けなかったですね、いろいろしつこい質問をしてごめんなさい >>121
普通に数学の手法なので、数学を勉強しようか
(ちなみに、君以外は全員ふつうにわかってるぞ) 完全解決してスッキリ
みんな時間とらせてしまってごめん
そしてありがとう fact 0 = 1 は、fact 0 = fact (fact 0)ではありません。 >>120
>>60で
> もちろんそのように考えてる
って書いてるけどそのように考えてなかったよね… >>122 が言っている「パターンマッチ」を彼が調べてくれるといいね >>92
だから、fact 1-1になった後、fact 0になるだろ?
そしたらfact 0 = 1になるんだよ。
数学の数学的帰納法ググれ。
fact 0 = 1
これはfactの引数が0なら強制的に1になると言ってる。
fact n = n * fact (n - 1)
これはfact nを解くには引数のnに、nより1つ小さい数をfactに渡したものを掛けたものと等しいと言っている。
(そして最終的にfact 0で1が返って全体の値が求まる)
fact 3
= 3 * fact (3 - 1)
= 3 * fact 2
= 3 * 2 * fact (2 - 1)
= 3 * 2 * fact 1
= 3 * 2 * 1 * fact (1 - 1)
= 3 * 2 * 1 * fact 0
= 3 * 2 * 1 * 1 ― fact 0 = 1より
= 6 ただし、fact 0の様な特殊な条件を上に書く必要がある(Haskellに限らず、どの言語も) スタック消費しない末尾再帰とか、まだ先があるのに先が思いやられる。。。
(末尾再帰も最近じゃCやJavaScriptでも効くらしい。実質ループだから使った事ないけど) 遅延評価や並行並列がデフォルトの言語ならばスタック消費しないのは当たり前である 人間の読解力なんて順調に行っても1日1行程度でしかない リストや配列には複数の要素がある
オブジェクトにも複数のメンバーがある
その一部が不要になってもメモリは全部残る
ここまでは言語に依存しない HaskelでWindowsアプリケーション作りたいですけどできるんですか? 問題は、何十年か前にそれができた人のコードを今コンパイルできるか
今できた人のコードを何十年後にコンパイルできるか
それができるのがC/C++で
他の言語はそれを不可能にして新しい言語を普及させたい さようなら遅延評価 2019-02-15
https://kazu-yamamoto.hatenablog.jp/entry/2019/02/15/115630
Haskellがとっつきにくい原因の一つに遅延評価がある。入門書では、無限リストと遅延
評価がことさら強調される。しかし、Haskellを業務で使ってみると、遅延評価が煩わしく
なってくる。遅延評価なしでもほとんどのことは実現できるし、メモリーの使用量は推測
できないし、あまりいいことはない。(中略)
、GHC 8.0 では、言語拡張 Strict と StrictData が提供された。この二つを使えば、
デフォルトの評価戦略が正格評価となる。
つまり、以下のコードの評価戦略は遅延評価だが、Strict と StrictData を用いると
正格評価となる。(中略)
Strict と StrictData をもう少しく知りたい人はStrict Haskellを読んでほしい。
純粋関数型データ構造を読んだ諸君、Haskellではデフォルトが遅延評価だからイマイチ
例題をうまく実装できないと思ったことだろう。でも、今なら簡単にできるのだ!(後略) xcodeで使えないのが致命的なんだよな・・
リンクはできるがUIがらみのコードは書けないわけで スレを読み直してて気づいたけど、>>60ってこういう意味で言ってたのね
もちろんそのように(>>57の前半のように)考えてる
fact 0 = 1の結果はすぐ(fact n = n * fact(n - 1)に)反映されるんじゃないの? もういいだろう ただ単に基本的文法すら知らない子じゃん とっつきにくいも聞き飽きたな
パワハラ上司に同じこと言えるのかと
本当にとっつきにくい相手はそういう輩だ ややこしいことをややこしい方法で簡単にするのがhaskell Pythonのように型を書かないやつはゴミクズ
とかいうハラスメントが一番の問題だから遅延評価は誤差の範囲内 一回しか変数に代入しない場合は副作用になりますか?
YES か NOでお答えください。
JavaScriptで言えばこういうコードです。
const a = foo(), b = bar(a), c = baz(b);
(const変数は再代入ができません) Haskellスレの皆さんこんにちは✨😃❗
突然ですがこのたびWeb制作板JavaScript質問スレにて、スレ民の総意により、
[1,2,3].map(v => (v += 2, v * v));
のv += 2は副作用ではない。
と決定しました!
ありがとう!ありがとう! >>152は再代入と(再代入しない)代入の違いがわからず
代入は副作用であると言い張っているマヌケが
再代入の例を出し、代入は副作用であると
結論づけようとしているだけなので無視してください。 >>153
?別の方と勘違いされているのでは??
話はシンプル。質問をして、その答えを得た。以下が全てです。この質問と答えに、前後の文脈など関係ありますか??
904 Name_Not_Found sage 2019/02/17(日) 00:42:09.09 ID:???
>>901
悪いけど以下の(ア)に入るのは1か2か答えてくれる?1か2の一文字書くだけだから出来るよね?
[1,2,3].map(v => (v += 2, v * v));
のv += 2は(ア)である
1. 副作用である
2. 副作用ではない
907 Name_Not_Found sage 2019/02/17(日) 00:44:40.52 ID:???
>>904
Wikipediaの2つの成立条件を考えれば、2. は迷惑だろ
908 907 sage typo 2019/02/17(日) 00:45:33.97 ID:???
× 2. は迷惑だろ
〇 2. であることは明白だろ あの?Haskellスレを荒らさないでくれますか?
関係ない話はJavaScriptスレに戻ってください >>155
おや?
>>151を書き込んだのはどなたですか?w
何か都合の悪いことでもあったのですか?w
大慌てで>>151を張りに来たようですが?w Haskellスレ民の方々どうも!
Web制作板JavaScript質問スレにて、
https://en.wikipedia.org/wiki/Side_effect_(computer_science)
の以下の文章について…
> One common demonstration of side effect behavior is that of the assignment operator in C++.
副作用の振る舞いの一般的なデモとしては、C++の代入演算子があります。
> For example, assignment returns the right operand and has the side effect of assigning that value to a variable.
例えば代入は右オペランドを返し、かつそれと同じ値を変数に代入するという副作用を持ちます。
スレ民の叡智を結集した結果、
・C++の代入演算子は副作用があるが、JavaScriptの代入演算子は副作用がない
・[1,2,3].map(v => (v += 2, v * v));
のv += 2は主作用を使っているのであって、副作用など使っていない!
と決定しました!
パチパチパチ〜
ありがとー!! 初期化と代入の違いはC++でさんざんやったやつだろ
C++には遅延評価がないから余裕じゃないのか Cのマクロ
#define fact(n) (((n)==0)?1:(n)*(fact((n)-1))
これだったら一見まともに見えて
実は無限ループする罠
fact(0)は
((0==0)?1:(0)*((((0)-1)==0)?1:((0)-1)*(....
となって無限ループ。
(ややこしいんで括弧の数とか間違って
るかもしれないけど)
C++でインライン関数で定義した場合は
論理式短絡評価で動くかもしれんが 再帰を含む関数がインライン展開されることを
期待するほうが間違いだったか... だめだわからん
fold_left :: (a -> b -> a) -> a -> [b] -> a
fold_left _ a [] = a
fold_left f a (x:xs) = fold_left f (f a x) xs
リストが a1 a2 a3のとき
folder_left f (f a a1) [a2 a3]
になることはわかる
その先の展開が何時間考えてもわからん
f(f(f(a,a1),a2),a3)になるってゆーんだが
イメージに繋がらない
お前らこんな難解なの本当に使いこなせてるの?
ここまでわかりにくいと有用なのか疑わしく思えて来る >>168
foldlなんて単なるループみたいなもんだし
今どきJavaでもやるくらい
分かるまでは変に抽象化しないで、具体例で考えるといいよ
folder_left f a [a1 a2 a3]
じゃなくて
folder_left (+) 0 [1, 2, 3]
で考えるとか
そしたら
folder_left f (f a a1) [a2, a3]は
folder_left (+) ((+) 0 1) [2, 3]になる
要は最初に
int sum = 0
for(int a : xs) sum = sum + a
と書くのと変わらない
sumへの蓄積を、変数への再代入ではなく次の関数への引数として書いてるだけ
どちらかというと、いわゆる関数型っぽいのはこういうのよりfoldrでリスト作ったりするときの方かな >>169
まったくわからない
例題載ってるとこにも似たようなことは書いてあるんだけども
ループで書くならすぐ終わる話だけど
ややこしすぎてイメージがつかめない
イメージがつかめたらその時点で理解終了なんだけど a2とa3が分離されそうなことはわかるんだけども
folder_left f (f a a1) [a2 a3]
^^^^
こいつがどこ行くのっていうのと
どこをどうやったら()で括られることになるのかイメージできない >>171
folder_left f (f a a1) [a2, a3]
になるところまではわかるんだよね?
そしたらまず括弧の中から先に計算するのはどの言語も普通だよね
だから先に(f a a1)の答えが出る
fは引数を2つとる関数だから、答えを出すのに支障はないよね
ここで(f a a1)の計算結果をz1としようか
そしたら上の式は
folder_left f z1 [a2, a3]になるよね?
そうすると、f、z1、[a2, a3]の3つの引数を使って、folder_leftがまた呼び出されるのがわかる?ここが再帰ね
folder_leftの定義は2つあるけど、[a2 a3]は空リスト([])じゃないから、下の
folder_left f a (x:xs)の方が呼ばれるよね?
ここでaはz1、xはa2、xsは [a3]だよね
だからベタで書くと
folder_left f (f z1 a2) [a3]になるよね?
同じように括弧の中が先に計算されるから、(f z1 a2)をz2としようか
そしたら
folder_left f z2 [a3]となる
また全く同じようにfolder_leftを呼び出すと、次は
folder_left f (f z2 a3) []となる
そして同じように(f z2 a3)をz3とすると、
folder_left f z3 []と書ける
ここでまたまたfolder_leftを呼び出してるわけだけど、最後のリストが空リストだよね
だからfolder_leftの2つの定義の内、上の方のfolder_left _ a [] = aが呼ばれる
上から順に呼び出し条件を見てるからね
ここでaはz3のことだから、最終的にz3が答えになる
じゃあz3が何かっていうと、(f z2 a3)だよね。そしてz2が何かっていうと、(f z1 a2)だよね
つまりz3は(f (f z1 a2) a3)のことだ
そして最後にz1は(f a a1)だから、結局
z3 == f (f (f a a1) a2) a3となる
これでどうだ >>172
()の中って完全に展開されるまで実行されないものと思ってた
例題もそんな書き方だったし
これならわかる!
ありがとう >>173
そこらへんは評価戦略の話であって別件だね
再帰の本質ではないよ
Haskellといえば遅延評価みたいなところがあるから混乱しやすいけどね
上で言うならz3こと(f (f (f a a1) a2) a3)を、最後までこの形で持って行って、最後にまとめて計算するのが遅延評価
上で書いたみたく適宜評価していくのが正格評価
Haskellだとfolder_leftは二種類あって、
遅延評価版がfoldl
正格評価版がfoldl'
ぶっちゃけ左畳み込みに関してはfoldlを使うことはない
全部foldl'でいい カリー化関数の意図がわからん
sum_of :: (Integer -> Integer, Integer, Integer) -> Integer
sum_of (f, n, m)
| n > m = 0
| otherwise = f n + sum_of (f, n + 1, m)
これはわかる
sum_of' :: (Integer -> Integer) -> Integer -> Integer -> Integer
sum_of' f n m
| n > m = 0
| otherwise = f n + sum_of' f (n + 1) m
どう見ても書き換えただけにしか見えないんだけどこれ意味あって書いてるのかな
カリー化って引数可変で動作する関数を定義するためのものって理解したけど
後者にはそんな意図が含まれてるように見えない >>175
やってるのは数式で書くと Σ[i=n..m] f(i) か
再帰をちょっと具体的に書き下さないと何のsumかわからんかった
それで多分やりたいのは
こういう風に個別の総和関数が手軽に作れますよみたいな話だと思う
タプルで定義されてるとこういう風にはいかない
(書けないことはないけどめんどくさい)
sumOfTwice :: Integer -> Integer -> Integer
sumOfTwice = sum_of (*2)
ここで(*2)とかできるのも
(*) :: Integer -> Integer -> Integer
がカリー化されてるおかげ
こういうのを部分適用と言って可変長引数とは異なる概念 >>176
(*2)の意味わからなくて前後調べたら演算子をカリー化できるとかあって
やっと意味わかったありがとう
しかも例題の先の先の方に有効な利用法書いてあったけど
なんかどうもサイトの進め方と合わないなー・・変えるかー
こんなこと書いてもなんか意味あんのだから何なんみたいな悶々パターンが多すぎる
とても簡単ですとか書いてあったら相当難しいフラグ確定
考え方が違うんだろうな 考え方を変えるのが関数型を学ぶ一番の目的だと思うけど、
合わないなら関数型あきらめればいいじゃん。
うちは論理型言語に全く馴染めなくて、それに時間使うのやめた。 そうじゃない
人を信じるのをあきらめて嘘を嘘と批判する
とても簡単ですと言った奴は嘘つきのクズであると しかしいいサイト全然ないなどうしたもんか
お前らどうやって習得したのよこんな難解な言語 例えばC#とF#の考え方は変わらないし
考え方を変えるというのも嘘だな
嘘に気付くのに1日かかるやつと5年以上かかるやつの差は大きい Prelude> let foo n = ¥x -> x * n
Prelude> :t foo
foo :: Num a => a -> a -> a
Prelude> let foo10 = foo 10
Prelude> :t foo10
foo10 :: Integer -> Integer
Prelude> foo10 10
100
Prelude> foo10 20
200
Prelude> let foo100 = foo 100
Prelude> foo100 10
1000
Prelude> foo100 20
2000
Prelude> let foo5 = foo 5
Prelude> foo5 10
50
Prelude> foo5 20
100
Prelude> :t foo (1.234 :: Double)
foo (1.234 :: Double) :: Double -> Double >>183のクロージャの説明がさっぱりわからない
関数を生成する関数を簡単に作ることができるって言ってるんだけど
やってることは定義を繰り返してるだけでちっとも生成してない
どういう意味で関数を生成したって言ってるんだろ・・
Stringで関数生成してevalで評価しましただったらわかるんだけど、これ違うよね
それともhaskellの場合は関数定義は関数生成としているのか・・わからん
一体これは何が言いたいのか・・
実はどうでもいいことで気にしなくてもいいなら納得するんだけども またHaskellのせいにしてるの?
以下は同等のJavaScriptだけど。
let foo = n => x => x * n;
let foo10 = foo(10);
foo10(10);
//=> 100
foo10(20);
//=> 200
let foo100 = foo(100);
foo100(10);
//=> 1000
foo100(20);
//=> 2000
let foo5 = foo(5);
foo5(10);
//=> 50
foo5(20);
//=> 100
てか何の言語なら知ってるんだっけ? >>186
そうじゃなくてこれ関数定義だけで生成なんかしてないよね?って話
ぱっと見パスしてもいいようなどうでもいいことにも見える
そうであれば次に行く
どうもHaskellは納得いかないことがあまりにも多いんだ
文化の違いなのか考え方の違いなのかわからんけど
CかObj-CかSmalltalk-80/VisualWorksで Cは実行時関数生成能力ないから仕方ないけど…
let foo10 = foo 10
は関数を返す関数fooに10を渡して、
関数(¥x -> x * 10)を得て(これが、ここが「生成」)
それにfoo10って名前を付けてるって理解は無理?
あなたこれまでに¥x -> x * 10って関数定義した覚えある?書いた覚えがあるのは¥x -> x * nでしょ?
まあ次行け次。 >>188
foo10は結局のところ ¥x->x*n を呼び出してるだけじゃないの?
¥x->x*10って関数を生成してないよね?
そういうことではない? C++だったらtemplate引数として渡したら定義で、コンストラクタに渡したら生成
静的と動的がわかるのが前提だからわからないならpythonかjavascriptから始めるべき >>190
PythonならBlenderで頂点やマテリアル抽出するときに必須だったから使ったことあるけど
インデント縛りで胃が溶けそうだった
正直もうやりたくない・・ >>189
> foo10は結局のところ ¥x->x*n を呼び出してるだけじゃないの?
Prelude> foo10 10
100
とかのこと言ってるんなら
let foo10 = foo 10
で生成した関数(¥x -> x * 10)を呼び出してるつまり
(¥x -> x * 10) 10
100
> ¥x->x*10って関数を生成してないよね?
してるよ
let foo10 = foo 10 の foo 10の部分で。
(生成のタイミングは今回置いとくとして) >>192
わかった!
無名関数で定義されてるからできるってことかー
納得できたありがとう
次行ってみる templateとコンストラクタとメソッドの考え方
関数と関数と関数の考え方
変わったのは見た目だけ >>194
C++は全く知らないのでそっちはなんとも 早速詰まった何を言ってるのかわからん
一般に、関数を呼び出す場合、関数を評価するための環境は空リストです。
最初に、引数がこの環境に追加されます。let で定義される局所変数もこの環境に追加されます。
もしも、環境に該当する変数が存在しない場合は大域変数を参照します。
たとえば、foo 5 と呼び出すと環境は次のようになります。
foo 5 ==> 環境 : [(n, 5)]
ghciで実行
Prelude> let foo n = ¥x -> x * n
Prelude> foo 5
<interactive>:2:1: error:
• No instance for (Show (Integer -> Integer))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
Prelude>
そりゃそうだよねぇ・・
なんなんだろう何が言いたいのかさっぱりわからない
本当にこんな説明でみんな理解してったの? >>196
そこクロージャの説明のとこでしょ? 読み飛ばしていいと思うよ
手元にHaskellの入門書何冊かあるけど目次や索引にクロージャ無いし
純粋関数型言語でありデフォルトで関数がカリー化されているHaskellに
クロージャとかいう概念は別に要らないと思う
部分適用便利だねってことがわかればおk >>197
そっかわかったありがとう!
関数の合成もすぐわかったのでさらに次行ってみる データ型の定義まで来た
なんというかやっぱりこのサイトこれからhaskell入門の人にはどうでもいい余計なこと書きすぎなんじゃ・・
と思った do構文がIO型だからこのように書ける・・というのがどうもしっくりこないけど
都合上こうするしかなかったってだけの話で特別な意味はないのかな
calc :: IO ()
calc = do
putStr "Input Integer1 > "
x <- readLn :: IO Integer
putStr "Input Integer2 > "
y <- readLn :: IO Integer
let a = x + y
b = x - y
c = x * y
d = x `div` y
n1 = show x
n2 = show y
putStrLn (n1 ++ "+" ++ n2 ++ "=" ++ show a)
putStrLn (n1 ++ "-" ++ n2 ++ "=" ++ show b)
putStrLn (n1 ++ "*" ++ n2 ++ "=" ++ show c)
putStrLn (n1 ++ "/" ++ n2 ++ "=" ++ show d) >>200
いちいち躓いたところで立ち止まらない
これは別に関数型がどうとかに限った話じゃなく、未知のジャンルの勉強の話
まず思考を殺して30回読み返す
学ぶは真似ぶから始まる >>202
じゃあモナドとflatMapを理解しきってからdo構文に進んでください
それ以外にないです 読んでいるサイトが悪いのではないかなあ
すごいH本とか
HaskellではなくてOcamlだけど浅井『プログラミングの基礎』とかを読んだ方が
良いレベルだと思う >>200
do は (>>=) の糖衣構文 (=分かりやすく見やすくするための別記法) なので最終的にはモナドと (>>=) を理解するまではしっくりこない。
https://qiita.com/saltheads/items/6025f69ba10267bbe3ee 最終的に>>=演算子オーバーロードを理解する頃には難易度がC++と同じ >>205
そういうことなら先に進んでもよさそう
リンク先の見たら変換可能なこともわかった
ありがとう! haskellのGUIは何が主流なの
gtkじゃネイティブUIに見えないからqtahとか?
もしくはhaskellではGUIを扱わないとか? 趣味でやってるが Threepenny 使ってる
簡単に組み合わせられるようになるかなと
Elm も学習中 書籍「Thinking with Types」の第1章をサンプルPDF版で読んでいるのですが、
19ページ目の Exercise 1.4-i でつまずいています。
数式 (a^b)^c と a^(b*c) が等しいことを Curry-Howard isomorphism を使って証明する問題ですが、
これは、
to :: (b -> c -> a) -> (b, c) -> a
from :: ((b, c) -> a) -> b -> c -> a
という型の Haskell の関数を見つけよ、と言うことですよね。
しかし、問題文に書かれている
to . from = id
from . to = id
の意味が分かりません。
to . from の型も from . to の型も共に id の型とは等しくないと思うのですが・・・ to :: (b -> c -> a) -> ((b, c) -> a)
from :: ((b, c) -> a) -> (b -> c -> a) Haskellにはファーストクラス多相関数がないから
idの型は単相なんだろう
単相のidという名前の同音異義語がちょっと多すぎるだけ >>209
思い出して今日発売のelm本、買おうかなと思ったら尼で売り切れててワロた。 下記の2つの関数の rank について
関数 f は rank 2、関数 g は rank 3 で合ってる?
f :: a -> (forall b. b -> c)
g :: a -> (forall b. b -> c) -> d >>212
やっと意味が分かりました。
ありがとうございした。 条件を満たす限り畳み込むfoldWhileみたいな関数がないのはなぜ?
scanとtakeWhileで出来なくもないけど無駄なリストが生成されちゃうよね scanした後はlast.takeWhileとかだと思いますがfusionされるので作られません >>217
ありがとうございます
fusion調べてみます haskell入門ほぼ読んだけどちょっと物足りなくてもうすこしhaskell勉強したい欲がある(目的は競プロとか月並みにaiとか)
なんかええ本ある? 数学の高速なライブラリとか圏論、モナドの解説あるやつで(数学は拒絶反応しない)
get programming with haskellとか並行並列とか多少気になってるけどどう? 初心者を抜けた後、実践へ進みたいのなら幾つか勧められる本はある。
しかし、更なる勉強がしたいのなら、勧められる本はない。
初心者用か、初心者を抜けたばかりの者にはまだ難しい本しかない。
特に君の目的(競プロやAI)に叶う本は今のところ皆無だ。
なので、ネットを漁れ。
あと質問がやや曖昧で、何を求めているのか分からん。
数学の高速なライブラリの何を求めてる?
それを自作できる知識なのか?
活用する知識なのか?
もしくは、仕組みが知りたい具体的なライブラリでもあるのか?
圏論やモナドにしても然り。
それらの何が知りたいのか具体的に言ってみ。 >>220
具体的には数学書のような理論本ですね 今のところ全然数学臭さがないので(コンピュータとは乖離してるかもしれないけど)
速度に関しては、命令型の書き方でないのでどうすれば速度が出る書き方が出来るかが一番興味あります
ai,競プロはやるとしたときの足掛かりが気になりました
このみっつのどれかが掘り下げられれば幸いです。 THUNKとかWHNFとかだろうけど
俺もここら辺の本とかあるなら読んでみたい >>221
「数学書のような理論本」 悪いが意味が分からん。
具体的に「何が知りたいのか」を言ってくれ。
理論と言うのが大雑派すぎる。
速度を上げる方法を学びたいのなら、
・Haskell High Performance Programming
・関数プログラミング 珠玉のアルゴリズムデザイン
この2つが正にうってつけだが、
「Haskell入門をほぼ読んだ」段階では挫折しそう。
AI や競プロは前レスでも言ったが本は無い。
AI は reinforcement leaning や deep leaning など技術範囲を絞ったワードと
haskell を組み合わせたキーワードでネット検索。
競プロは実際の競技で提出されたソースをたくさん読んで真似しろ。 >>223
どうもありがとうございます。図書館で覗いてみます
具体的には、数学との関わりを体系だって書いてる書籍を探してましたが、そりゃ個々のキーワードで探す方が手っ取り早くて色々漁れますわな 競プロにHaskellはどうなんだ…?
良くわからんけどSTモナド使いまくる感じになるのかな
あるいは珠玉のアルゴリズムを理解仕切った超人達の集まりなのか >>221,223
珠玉のアルゴリズムデザインへの入門としては同じ著者の
『Haskellによる関数プログラミングの思考法』
(旧版名は『関数プログラミング入門 ―Haskellで学ぶ原理と技法―』)
がいいと思う
他の入門書よりは数学色が強いし
等式変形によって効率を改善していく運算も割と丁寧に扱っていると思う
あとは『純粋関数型データ構造』とかも参考になるかも?
ただ競プロならSTRefとかSTUArrayとかに習熟するほうが
手っ取り早いし有力かも >>225 >>226
例えば AtCoder の参加者のコードを見てみると分かるが、
STモナドなんて使ってるヤツはいない。
そもそも、haskell に慣れたら、STモナドなんて使いにくいだけだろ。
競プロみたいな短く速いコードを書く必要があるなら尚更。
珠玉本を理解しきった者かどうかは知らんが、
極端に短いコードで解いてくるヤツは、
どちらかといえば数学の知識が豊富なんじゃないかな。
問題文を数学の世界に落とし込む事に長けているように見える。
コンテストにもよるが、競技プログラミングは
個人的にはアルゴリズム力よりも数学力がより大事だと思ってる。
例えば Project Euler の高番号問題をシンプルに解けるヤツは競技も強そう。 >>226 >>227
どうもありがとうございます。StateとかSTは内部処理はよくわからないけど便利なので使い方おぼえておきたいとこですね >>229
それでも理解したいのなら質問すればいい instance head ってよく聞くけど、
これは instance 宣言のどの部分のこと?
例えば次の宣言の場合
instance (Foo a) => Bar (Baz a b) | a -> b where
・(Foo a)
・Bar (Baz a b)
・Bar (Baz a b) | a -> b
・instance キーワードと where キーワードの間の全部
・その他
どれ? >>231
すまん、instance 宣言に関数従属は無いよな。
改めて、
instance (Foo a) => Bar (Baz a) where
この例だとどこが instance head なんだ? >>231
自己解決した。
instance head は => より右側かつ where より左側の部分だった。
スレ汚してすまない。 HaskellのGUI(Gtk2hs)でカウンター作ってみた。
import Graphics.UI.Gtk
main = do
initGUI
window <- windowNew
set window [windowTitle := "counter", containerBorderWidth := 10]
mainbox <- vBoxNew True 5
containerAdd window mainbox
label <- labelNewWithMnemonic "0"
boxPackStart mainbox label PackNatural 0
countbtn <- buttonNewWithLabel "Count"
clrbtn <- buttonNewWithLabel "Clear"
boxPackStart mainbox countbtn PackNatural 0
boxPackEnd mainbox clrbtn PackNatural 0
widgetShowAll window
onClicked countbtn (labelGetLabel label >>= \n -> labelSetText label (show (1 + (read n))))
onClicked clrbtn (labelSetText label "0")
onDestroy window mainQuit
mainGUI label <- labelNewWithMnemonic "0"
boxPackStart mainbox label PackNatural 0
countbtn <- buttonNewWithLabel "Count"
clrbtn <- buttonNewWithLabel "Clear"
boxPackStart mainbox countbtn PackNatural 0
boxPackEnd mainbox clrbtn PackNatural 0
widgetShowAll window
onClicked countbtn (labelGetLabel label >>= \n -> labelSetText label (show (1 + (read n))))
onClicked clrbtn (labelSetText label "0")
onDestroy window mainQuit
mainGUI boxPackStart mainbox countbtn PackNatural 0
boxPackEnd mainbox clrbtn PackNatural 0
widgetShowAll window
onClicked countbtn (labelGetLabel label >>= \n -> labelSetText label (show (1 + (read n))))
onClicked clrbtn (labelSetText label "0")
onDestroy window mainQuit
mainGUI コマンドラインでエンターを押すごとに数字が増えていく(Ctrl+C押すまで止まらない)
Haskellコード
main = mapM_ (\n -> print n >> getLine) [0..]
out:
0
1
2
3
4 急にどしたんww
gtk2hsのドキュメントがHackageから消えてるのは気のせい? 無限ポップアップ上げるやつ現れないとは高尚なスレ
リストで遅延評価使うのがなかなかハスケルっぽい 一応、カウンターみたいなのは純粋関数型言語には作れない言われてたから、作ってみた。
確かにi++みたいな事は出来ないが、違う方法で参照透明性を確保しつつ実現出来ると実感。
(個人的にHaskellには副作用はあると考えているが、参照透明性は崩れないとも考えている) そりゃ副作用はあるよ。
じゃなきゃIO処理できない。
haskell の特徴は純粋な関数から副作用のある関数を呼べないこと。 うい。
そう言う仕組みになってるくせに、IOな関数も扱いとしては純粋な関数と同じ扱いなのが気に入ってます。
(型に気をつけていれば自然とそうなるし、普通にprint関数と純粋関数を関数合成出来るのが好き) 純粋関数型言語でカウンタが作れないというのは、
同じ関数を呼び出した結果がカウントアップされるような関数のこと。
pythonで書くとこんな感じ。
>>> def create_counter():
n = 0
def counter():
nonlocal n
n += 1
return n
return counter
>>> counter = create_counter()
>>> counter()
1
>>> counter()
2 >>244
そうなんですが、純粋関数型言語の場合、その関数を何回呼び出したのかカウントする関数を作るみたいな視点の切り替えで対処するのではと。
つまり自身のファイルを読み込んで自身(counter関数)を
a = counter
b = counter
a = 1
b = 2
に置き換える関数なら作れます。
欲しいのは結果であり、動作ではなく結果が同じなら良いと言う解釈です。 終了やカウントクリアに対応してみた。
import System.Exit
main = do putStrLn "quit code is 'q', count clear code 'c'"
mapM_ (\n -> print n >> getLine >>= f) [0..]
f "quit" = exitWith ExitSuccess
f "clear" = main
f _ = return () 副作用もカウンタもGUIもHaskellでできる (Haskellで作れるとは言っていない) まあ要はcounter関数はswap関数と同じですよ。
手続き型言語ではソートや繰り返しに必須ですが、関数型言語で各種ソート作る時にswap関数は使った事がない。
木を見て森を見ずというか、counter関数を何に使うの?って話で、カウンターとしての用途なら再帰関数の引数でf (x + 1)とか渡せば良いだけですし。
loop10 n | n > 10 = return ()
loop10 n = print n >> getLine >> loop10 (n + 1) つまりHaskell(というかElm?)で無限アラート書いとけば捕まらなかった? Haskellの再帰は場合によってはヒープを使うから
10^9回ぐらい閉じる奴がいたらサイバーテロとして扱われてたかもしれない そこは気を付けなきゃだけど(と言うか、スタックは兎も角ヒープ使うってreverseみたいにリスト溜め込むとかだけで、手続き型言語でもあり得る場面に限られそうだが)、
むしろモナドな再帰(IOはもちろん、リスト->リストな再帰も)がループになると言うのは、
手続き型言語よりも再帰でスタック使うケースが少ないと言う魅力もある。
(ここは手続き型言語が末尾再帰最適化に対応しても追いつけない所)
>>246 の通り、mainを再帰的に呼び出してもループになると言うのは知る限り手続き型言語では見たことない。
main変数が他の言語で言うmain関数的な動きをしているのも、圏論的には変数は引数無しの関数と見做せるから。
main変数を評価しようとすると束縛されたプログラムが動き出す。
n = 1 ― 変数であり、常に1を返す引数無しの関数 いやGHCが与えるスタックはヒープなんだよ
Cのコールスタックみたいな固定領域じゃなくてね
それもデフォルトで最大メモリの8割というデカさだから
うっかり非末尾再帰を放っておこうものならスワップ地獄に陥る 非末尾再帰を末尾再帰に自動変換するのって技術的に不可能?
末尾再帰ってなんか無理やり感あるよね フィボナッチを再帰で書くと定義がそのまま動く感動が味わえるのに末尾再帰に書き直すととたんに台無しになるよねw ヒープにあろうがスタックにあろうが末尾再帰に意識して書けばまず解決する問題だね。
ghciやrunghcみたいなスクリプト形式だと最適化(部分的な正格評価)が不十分で
sum’ n [] = n
sum’ n (x:xs) = sum’ (n + x) xs
という末尾再帰があった場合、
sum’ 0 [1,2,3]
= sum’ (0 + 1) [2,3]
= sum’ ((0 + 1)+ 2) [3]
= sum’ (((0 + 1)+ 2)+ 3) []
みたいに(遅延評価のせいで)結果を入れる変数の方でスタック消費するけども、コンパイラ(ghc)の方はこの問題は無い。 >>254
別に数列(リスト)から取り出す形にすれば末尾再帰にする必要ないでしょ。
main = print $ fibs!!3 ― 0から数えて3番目
where fibs = 0:1:zipWith (+) fibs (tail fibs)
foldlの正格評価版 foldl’みたいにzipWithの正格評価版作って差し替えると高速化する。
(このネタ書いてたブログの人はzipWith’を標準で入れてて欲しいって書いてた)
zipWith’ f (x:xs) (y:ys) = seq a $ a:zipWith f xs ys
where a = f x y
zipWith’ _ _ _ = [] >>256
定義そのままで書きたいって話であって末尾再帰だからダメとは言ってないでござるよ 「感動」はダメとは言わないが意味がわからないと言いたい 自然に書くなら数学の定義通り書くよね
でも今のコンピュータの制約上仕方なく末尾再帰にしないといけないよね
自然に書ける日は来ないのかなあってある種当たり前の感覚だと思うけど コンピューターの制約で変えねばならないならば定義に問題がある
定義は可能な限り一般に適用可能でなければならない
よって定義を変えればよい 感情をそのまま言語化できるなら犬や猫も言葉を話せることになる
実際には感情と言語は一致しないので感情をそのまま言語化することはない 何か噛み合ってないな
自然な感覚に近い表現ができるほうが可読性高いよねくらいの話でしかないはずなのに
今何の話になってるんだ?? 言葉を話さない動物やAIには言語の制約がない
ゆえに動物やAIは人間を超える可能性がある
壮大な詭弁だ 末尾再帰=ループ
分岐が発生するとこの関係が崩れる 何か変なとこに手出しちゃったみたいですね
もうやめときます
スレ汚し失礼しました 可読性で思い出したが
ソースを読まなくても使ってみればわかることは読まない方がいい
読んだときの自然な感覚なんかよりも、そもそも読まないのが最も自然 可読性をあげるためだけに型に別名つけるのってどうなの
type Description = Text
みたいなやつ 読むコストを下げるためだけにギャンブル
○○のコストは安いというのが本当か嘘かを賭ける
賭けないのが最も安いと思わないか >>259
https://i.imgur.com/816HQOu.jpg
https://i.imgur.com/wTI8fNg.jpg
一応、末尾再帰も式変形した定義通りなんだけどね。
fib3 0 a _ = a
fib3 n a b = fib3 (n - 1) b (b + a)
n = フィボナッチ数のn番目(fib n)
a = fib nの時のフィボナッチ数
b = fib (n + 1) の時のフィボナッチ数
fib3 nはfib3 (n - 1)のbがaになり、b(fib3 (n + 1))はfib3 (n - 1)のb(fib3 n) と a(fib3 (n - 1))を足したものである。 >>269 賭けない、は具体的には何? 型シノニムを使わないということ? >>271
使うのは自由だが可読性の勉強等はしないということ >>272
悩んでないでスタイルを決め打ちして自分が自然だと思える書き方で行く、みたいな感じですか そんな言葉は使う必要がねーんだ
書き方は決まってないのにもうすでに書き終わってるからだ やっぱりHaskellは常人向けではないんですね
Ocamlやります そういえば言語も決まってなかったな
常人は言語を決めないとプログラムを書けないってマジ? >>275
Windowsでは、昔のrubyみたいな状況なので、
それ以外のプラットフォームでやるのがいいよー よく判らないアドバイスだったな…
勉強・研究しないで突っ込むのはそっちの方が賭けてる感あるし、
すぐに書き終えるなら確かにそういう難しさはないが、
ソフトウェアのプロジェクトって面白いものは大抵長くなると思う。
>>277
Windows環境はWSLではダメなん? >>261
感情表現と言うように感情はあくまでイメージ想起性のもので
文法を持ってないものだと思う。
感情をそのまま言語化なんて人間でもしてないだろ。
あくまで論理的内容の会話文章の表現に感情を想起させる表現を
選んで論理としては同じだけれど得られるイメージが異なる文を
作っているだけだと思う。
そこで文を構成するために選ぶ表現がやたら極端なときに、感情的と評されているだけで。
ていうかおじさんになったしもう無理 >>279
得られるイメージが変わってしまうのはコンピュータの制約のせいだよ
fibのイメージをそのまま表現できたら感動するのになあ
この状況ではコンピュータの制約は変えたいがイメージは変えたくない
「論理としては同じだけれど得られるイメージが異なる」という想定は大外れ コンピュータの制約が悪夢のようだから消去法でイメージ
あほなことしてるだろ
俺達なんだぜこれ イメージないと妥当性の判断もできんぞ。
これだって
書き込み内容を読んで
内容から推測される人物像をいままでの記憶から割り出して
そういう人物に対してかつてもった心象(イメージ)を
この場合の想定(先入観)として設定して
否定的判断をするという内容を伝達しているだろ
大体こういうプロセスじゃね? 数学の世界で効率を全く重視してないわけじゃないからな。無限の速度のCPU上なら同じと見なせるってだけで。
末尾再帰のfibとか数学的だからアーキテクチャ関係なく元の定義より速い。
行列苦手だから書けないが、もっと速い行列バージョンも存在する。 これはPrologについて書かれているが、ここで話題にしてるのはこの記事と同じ議論だろう?
宣言型プログラミングの可能性と限界
https://thinkit.co.jp/article/157/3 全く読んでないがパラダイムと論理は同じではない
パラダイムの限界と論理の限界は同じではない >>284
>末尾再帰のfib
fib が末尾再帰でかけますか? sum x:xs = x + sum(xs)
は数学っぽく見えるけどアキュムレータ噛ますと途端にループに見える不思議 アキュムレータは余再帰っぽく見える
数学っぽいの反対は余再帰っぽい説 Haskell知らんでも無意識に >>270 みたいな式を思い描いて
for文とかに落とし込んでる感じじゃね?
n回繰り返すのが昇順か降順かの違いだけで。
Python
def fib(n):
temp = 0
a = 0
b = 1
for i in range(n):
temp = a
a = b
b = b + temp
return a
for i in range(10 + 1):
print(fib(i))
Haskell
main = mapM_ (print.fib) [0..10]
fib n = fib' n 0 1
where
fib' 0 a _ = a
fib' n a b = fib' (n - 1) b (b + a) 誰でも頭が良くなる、プログラムが書けるようになる方法が発見される 42162
https://you-can-program.hatenablog.jp 自然数が射(関数)になっていると言う感覚が分かった気がする。
Haskellで書けないけど、書けるとするなら
1 = 1
1という名前の1を返す引数無しの関数。 記号的な1を1と書き、概念的な1をチャーチ数で表現するなら
1 = succ zero トートロジーとかチンプンカンプンな高卒なんで。。。
補足説明や訂正があったら勉強になります( ̄^ ̄)ゞ ラムダ的な自然数は高階関数を使うけど、圏論は冪を使わないことが多い Haskell でもsuccって関数ありましたね。。。
私が
1 = succ zeroで表現したかったのは、どんな数体系でも1と表現される何かという意味での1です。
例えば16進数の10はAと表現されますのですが、
A = 10
とすると10が16進数では10進数の16になるので10進数でも16進数でも10として扱われる概念としてチャーチ数にしたかったのですが、
チャーチ数も含めた全ての数体系で10として扱われる何かを表現したいみたいな。
うーん。。。表現力が乏しくてすみません。 本当の所は
Int $ succ Zero
というような頭部正規形で表される関数のシンタックスシュガーだと思う ・チャーチ数はペアノシステムの1つの実装である
・任意のペアノシステムは(適当な公理のもとで)互いに同型である
みたいな話? >>303
> HNFは射ではない
> そもそも圏論にHNFはない
こういう表現は間違い
何が射かであり何が圏でないかは、どんな圏を考えているかに依存する
例えばだが、単純な型付λ計算(型の集まりが直積型の構成と関数型の構成について閉じている)に対応する圏、つまり単純な型とそれで型付けされるλ項の成す圏を考えることができる
そこでは、対象は個々の型で、射はλ項だ
そして個々のλ項は、そのλ項の中に現れる自由変数の各々の型の積対象からλ項全体への型という対象への射と考えるというものだ
この場合、λ抽象があるので冪対象が必要になり、従って、この単純な型付λ計算に対応する圏は必然的に積閉包圏というタイプの圏になる
これはいわゆる“categorical type theory”(圏論的型理論)の最も簡単な具体例だ
この圏の場合は単純な型付けに関してwell-typedなλ項は全て射として認められるのでもちろんhead normal formになっているλ項もwell-typedである限りは射だ Haskellの開発環境で、ブレークポイント張って評価中の変数の値を見る、みたいなのって出来ますかね?
Visual Studioのローカルウィンドウ的なの。
普段はSpacemacs使っててREPLで評価しては進め、評価しては進め、みたいな感じでやってます。 並行並列言語Haskellの基本と特徴
https://logmi.jp/tech/articles/321095
2018年11月10日、Haskell-jpが主催するイベント「Haskell Day 2018」が開催されました。
純粋関数型プログラミング言語Haskellをテーマに、Haskellに興味のある人から入門者、
ちょっとできる人まで、様々な層に向けたプレゼンテーションを行った本イベント。実務
から研究まで、幅広いHaskellの事例を共有します。プレゼンテーション「並列並行言語
Haskell 」に登壇したのは、syocy氏。講演資料はこちら (↓)(後略)
https://speakerdeck.com/syocy/bing-lie-bing-xing-yan-yu-haskell
https://speakerd.s3.amazonaws.com/presentations/07d92af9d7aa40bca6cc3959d3f56b28/parallel-and-concurrent.pdf cabalのnew-から始まるnixスタイルコマンドが出来たからtackつかう意味あまりないですよね >>309
v2-build だっけ? よく知らないが stack いらなくなるやつなんだ? stack or cabal どっちを使えばいいんだ >>312
迷う理由がわからない
現時点で好きな方を使えばいいのでは?
どっちを使っても、後で後悔することなんてないと思うが >>314
もはや同等とみていいの?
一長一短がイマイチ見えないので比較できない。 >>315
自分で情報を得られず、比較できなくて選べないくらいなら、
一長一短なんか考えずに、今好きな方や気になる方を使えば良いんだよ。
stackを長い間使ってきたから今後も使い続ける、でもいいし、
新しいcabalに興味が沸いたからcabal使ってみる、でもいい。
例えばパーサーライブラリ、Webライブラリ、FRPライブラリなどは色々あるけど、
いちいち「一長一短を比較した上で」選ぶ人はそんなに多くないでしょう。
みんな取りあえず何か一つ使ってみて、他に興味が湧いたら浮気してみて、
それからでしょ、比較するのは。 >>316
両方の一長一短をちゃんと比較して紹介するのは、
記事や本を書くプロや、意欲のある人に任せればいいと思う。
紹介のプロじゃないのなら、自分が好きな方を精一杯アピールすればいい。
それもできずに、初心者にどちらを紹介しようか悩むのなら、順番が違う。
どちらか一方でもアピールできるくらい使い込むのが何よりも先でしょ。 まぁこの手の選択にある程度以上責任持って助言するのは難しいんだよな。
少なくとも両方使ってないとどっちがいいとか言えないし。
ほとんどの人が最初に使った方をそのまま使い続けるもんじゃね。
私もcabalしかつかったことないし。 「みんなの見解を聞く」も自分で情報を得る過程のひとつだと思ってるんだが
記名ネットではしにくい無責任方言もここなら言えるでしょ まだキチンと検討していないが、自作したツールをbrewとかで公開するとき、ビルドツールを依存に含める必要が出てくると思う。予めどっちかを使うかは決めておきたい。
バージョンを重ねるなかでフラフラ変えるのは避けたい。
あとcabalだとコンパイラを替えるときはghcupなる別ツールを使うの? これだとクロスコンパイラはどうなる。
複数のアーキテクチャのための成果物をビルドするとき、ghcup set ... && cabal build && ghcup set ... && cabal build ... みたいにいちいち指定しないといけないのかしら。
コレを解決するにはghcupにパッチを当てるかcabalを改造するか、スクリプトを書くかするわけだ。その点 stack build はコマンド一発なのに。
俺は年間50時間くらいstackのパッチや関連ツールを書いてきた。このままで行けるならいいが、stack がいずれオワコンになるなら早めに見切りつけて時間節約したい。
新元号が30年続くなら令和中に1500時間も浪費することになるんだぜ。 >>320
> 記名ネットではしにくい無責任方言もここなら言えるでしょ
そんなレスは情報ではないのでは?
ただのノイズでしょ(ノイズの全てがゴミとは言わないが)。
本当に情報を得たいのなら、時間の無駄だよ。
もし、そんなのを参考にどっちか決められるのなら、
初めからルーレットで決めるのと大して変わらないのでは?
「自分で情報を得る」の第一歩は、ビルドツールで一番何がしたいかを決めて、
それが出来るか、やりやすいかを「公式ドキュメント」を見て調べる事だよ。
stackとcabalの公式ドキュメントを見て比較して、
それでも分からない部分をピンポイントでSNSや掲示板などで質問する、
それが二歩目だと思う。 伸びてると思ったら。。。
今の所stackかな。
cabalは依存関係で過去に評判悪かったから、新しいのの評判が固まったらかな。 >>322
調査を並行してやっちゃいけない理由はないでしょ。聞くだけならタダやし。
スレ民の意見をノイズだなんて思ったことないよ。自分にない視点や個人的使用感、気づきにくい落とし穴を教えてもらえるかも。
俺の雑感はstackは不備だけでなくバグも多かった気がする。.stack-workを消したらビルドが直ったみたいなことが何回かあったと思う。
stackのメリットは、
(ghcupの方針が変わらないなら)コンパイラの導入まで自動でやってくれるので、例えばHaskellスクリプトを書いてシェバンにstack、
以降に依存ライブラリを書いておけばいつでもどこでも動く(HackageとStackageが活きてるかぎり)、必要なものを都度自動で用意してくれる。
stackのデメリットは、
設定ファイルが多すぎる。プロジェクトレベルでは stack.yaml, package.yaml, Hoobar.cabal
と、どれに何を書くかが判りづらい、いちいち引っかかる。 >>324
無責任放言がノイズなんだよ。
で、その全てがゴミとは言わないとも言ってる。 >>325 前半は反論したし、後半は批判してないですよ。 凄いH本の中国語版見る機会があって、
漢字の用法がカタカナ語より
しっくりすると思ったんですけどどうでしょうか。
模式: パターン
門衛: ガード
類型類: 型クラス
さすがにモナドは漢字翻訳難しいみたいですが。 その程度のカタカナがしっくり来なかった人生を反省するんだ 慣れとしっくりくるのは別物だけどな
無意味刺激と有意味刺激、表音文字と表意文字に対する認知は先天性の個人差があるんだからあまり他人の人生なんて分かりもしないものに言及するべきではない
どちらにせよ今の中国は学術用語を積極的に訳する文化ではあるよね
Haskellに限らずclassや他の用語もそれに類した漢字が用いられてそう
ただこれも漢字の意味が時代によって変化してくると正しい用語認識を阻害しうるのは現代日本でいくらか見られているし、一長一短と個人差だね かつてアルゴリズムを算法とかコンパイルを翻訳とか
一部で言っていましたね。
モナドアクションを算法と訳すならモナドは法かぁ
などと連想してみました。 漢字に訳する場合どっか権威のあるところが決める必要があるよね
そういうところがめんどくさい 大陸だと結構あちこちで勝手に翻訳されたり
輸入されていずれ収斂されていくっていう
感じだった。
日本でも官公庁の訳語が定着しないことも
多いよね。 流れも読まずminからmaxまでのランダムな数のリスト(要素数n)を得る関数作って見た。
takerand _ _ xs 0 = return xs
takerand mn mx xs n = do
x <- randomRIO (mn, mx)
takerand mn mx (x:xs) (n - 1)
使い方は
rs <- takerand 1 6 [] 10
これで1ー6までのランダムな数が10個入ったリストが手に入る。 流れも読まずminからmaxまでのランダムな数のリスト(要素数n)を得る関数作って見た。
takerand _ _ xs 0 = return xs
takerand mn mx xs n = do
x <- randomRIO (mn, mx)
takerand mn mx (x:xs) (n - 1)
使い方は
rs <- takerand 1 6 [] 10
これで1ー6までのランダムな数が10個入ったリストが手に入る。 >>334
それなら、getStdGen と randomRs と take でいいのでは?
takerand mn mx n = getStdGen >>= return . take n . randomRs (mn, mx)
あるいは
takerand mn mx n = take n . randomRs (mn, mx) <$> getStdGen >>335
いいのでは、と言うのは失礼な言い方だった。
こういう方法もあるよ、と言うことで。 >>335
そう言うのがあったのね。。。
thanks. Arrowised FRP を 矢矧のFRP とかいうのは好き 型クラスの訳語 類型類 は、kindの 類 とごっちゃになるな、と思ったけど、
kindは 種 が主流なのか >>339
主流というか、それ以外に聞いたことがない すみませんHaskellでアート芸術方面のプログラミングをしたい場合
既存の表示用ライブラリは導入からして難しそうな印象があるので
表示はProcessingに任せるという方法を考えていますが、
http://hackage.haskell.org/package/processing-for-haskell
もしそういう方面に詳しい人がいましたら
それについての助言を頂きたいです。 >>342
なにを助言してほしいのか具体的に明確に言ってくれ。 >>343
説明が不十分ですみません。
アート芸術のプログラミングを行う場合
表示は既存ライブラリは使わずに
Haskell-Processing連携ライブラリを使って
データ処理と表示を切り分けた方が
簡単なのではないだろうかという質問でした。
https://github.com/anton-k/processing-for-haskell/blob/master/tutorial/QuickStartForProcessingers.md
表示はProcessingで行います。 >>344
データ処理と表示処理を切り分けた方が開発が楽になるのはその通り。
でも、グラフィックス ライブラリに何を使うかと、
楽に切り分けできるかどうかは、一般には関係ない。
特に haskell のグラフィックス ライブラリはたいてい EDSL 形式になっているから、
どれを使おうが、切り分けの楽さは大して変わらない。
後はもうライブラリの表現力が求めるレベルにあるかどうかと、
個人の経験や慣れ、趣味の問題だ。
Processing に慣れているなら processing-for-haskell でいいだろう。
個人的には gross が好き。
ところで、既存のライブラリって何だ?
processing-for-haskell は 2016 年でアップデートが止まってるが、
これは既存ではないの? >>345
ありがとうございます。理解しました。
参考にしたのが School of Expression だったので
情報が古くprocessing-for-haskellが
最新の物と思えて勘違いしてました。 >>344
そういうことをしたいならProcessingだけでやった方が手間かからない
Haskellで書けば楽になるとかそんなことは一切ないので >>348
「haskellで」アート芸術方面のプログラミングをするには、という質問だと思う。
ジェネラティブアートなんか haskell にもってこいじゃないかな。
もちろん、Processing の得意分野でもあるんだが、
宣言的に書ける haskell もけっこうマッチするのでは?
全て型プログラミングで生成とかもできそう。 f xs = let g = \x -> 2 * x in map g xs
この場合、ラムダは最初に一回メモリにアロケートされて g に束縛されるよね。
でも、もしかして、
f xs = map (\x -> 2 * x) xs
これって、f が呼ばれる度に map の第一引数のコード(ラムダ)がメモリにアロケートされるの? クロージャにしなくてもいいラムダはただの関数として扱われるんじゃない?
というか上のコードならセーフっていうのはgを使いまわしてくれるから?
そんな気の利いた処理系なら下のラムダも使いまわしてくれそうだけど その辺り、実際にどんな実行コードが生成されるかに関しては、
コンパイラ(GHC)に聞いてくれ、としか言いようがない
インライン展開とかクロージャ変換といったコンパイラ技法を学ぶことを勧める
関数型言語だからTiger本とか ラムダは何も簡約しなくても最初からWHNFじゃないのか
最初からWHNFならサンクとか不要だから普通の言語と同じでいい >>350
ラムダ式が動的に生成されるものと思っているのなら間違い
この場合は単なる関数として展開されている なるほど、納得できた。
これからは安心して引数にラムダを直接書ける。
ありがとう。 mtl によるモナド合成はモナド則を保存しない
マジかよ失望しました。mtl は窓から投げ捨てます 動的型付けに比べて静的型付けの方が優れている、は常に真?
実はHaskellで動的プログラミングをやる話を読んで、
あれっコレ意外といいじゃんと思ってしまったんだ。 次にお前らは『優れているを定義してくれ』と言うッ! 任意の言語に丸投げするシェルスクリプトはズル
文字列をevalするやつもズル
ズルをする必要がない言語は優れている
どうせこんな感じだろうと思ってる いくつかの基準が思いつく。
速い・短い・アシストが手厚い・理解しやすい・バグが混入しにくい…
>>359
「ズル」には悪い、の意味が予め含まれていると思うので納得できない。
evalを用いた場合に比べて静的型の解決の方が優れているのを示す必要があるでしょう。 格闘技ですら、反則には反則負けという意味が含まれている sequence_の使い所が分からん。。。
mapM_使った方が短くなるし。
うーむ。。。
渡すリストにIOな関数含められる=IOな関数を使う
リスト内包表記も使えるのは良いけど、mapM_のが簡潔。
import Data.List
import System
main = mapM_ put $ zip hellos marks
-- sequence_ [put (x,y) | (x,y) <- zip hellos marks]
hellos = (cycle.tails) "Hello World!!"
marks = cycle ["/","|","\\","--"]
put (x,y) = do putStrLn (x ++ "\n" ++ y)
mapM_ (\_ -> putStr "") [1..50000]
system "clear" hellos = (cycle.tails) "Hello World!!"
marks = cycle ["/","|","\\","--"]
put (x,y) = do putStrLn (x ++ "\n" ++ y)
mapM_ (\_ -> putStr "") [1..50000]
system "clear" >>363
モナディックアクションを構造に入れて使うとき重宝するよ。
main = sequence_ . (map (putStr "log:" >>)) $ [print "hoo",putStr "bar"]
個々のアクションを好きに調整できる(例ではそれぞれに前処理を足した)。 >>365
ありがとう。
いつか役立てたいものです。 別件なのですが、俺俺Eq型クラス(MyEq)を作って見ているのですが、
HugsだとNum a型のインスタンスを作れるのに、GHCだとエラーが出ます。
経験ある方、いらっしゃいますでしょうか?
main = do print $ 1 === 1
print $ 1 /== 1
print $ 1 === 2
print $ 1 /== 2
class MyEq a where
(===),(/==) :: a -> a -> Bool
x === y = not (x /== y)
x /== y = not (x === y)
instance (Num a) => MyEq a where
x === x' = isZero (x - x')
x /== x' = not (x === x')
isZero 0 = True
isZero _ = False
GHCだと全ての型をインスタンスにしろ的なエラーメッセージが出ます。。。
スマートな方法があれば。。。 >>363
mapじゃなくunfoldrで[IO a]を作ってもいい
>>367
エラーは「インスタンスにする型はこれこれこういう形にしろ」って意味
instance (Num a) => MyEq a みたいな形を許すと
instance (MyEq a) => Num a とかもできて意味わからなくなるから
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
というおまじないを使って制約を取っ払う >>357
オブジェクトファースト動的解決脳だとHaskellはただめんどくさいだけの言語にしか見えない
利点とされていることが欠点にしか見えないもある "--port=" <> ( 8000 <> 80 )
これが "--port=8080" になって欲しい、みたいな? >>371
それは暗黙の型キャストとかの話な気もするが
String と Num a との積を勝手に解決するなよって思う ...でも演算子を上述のように定義すると半群の結合則を満たさない。
dynamicパッケージでもそうされてなくて、結果は"--port=800080"になります。
動的プログラミングを求める人は柔軟に使える演算が欲しくて、
Haskellのデフォルトの定義は型変換がただ面倒くさい。
369が言いたかったのは例えばそういう事かなと解釈しました。 >>368
おまじない!!
ありがとうございます。
これで行けそうですm(_ _)m 何やってるのかよく分からんけど、おまじないで解決
haskellの初心者時代って、こういうの他言語に比べて多いよね
どうにか分かりやすく説明できないものか、いつも悩む >>374
まあ確かに数値計算するときにfromIntegralだのrealToFracだのをゴテゴテ書くのは
(それを要求される理屈はわかっていても)面倒くさい
そこを「柔軟」にしていくと人が書き間違えたときに教えてくれなくなるから
結局は書きやすさと安全性とのトレードオフだよなあ 結局、マクロ、関数、型チェック以外にプログラムにできることなんてない。
バカがバカな夢を見る。 Cは関数の定義はゴテゴテ書くが演算子の定義は何も書かなかった
C++が演算子を定義するようになったからHaskellも影響を受けたんじゃないか
数学的証明だけでなく、歴史を巻き添えにして議論しないと現実は見えない すみません、
凄いH書籍で学習していて疑問に思ったのですが
型クラス中級で、真理値の様な物を持ちうる型、
JavaScriptのfalsyな値を持つ型を作る実習で
Intや[ ]を独自のYesNo型のインスタンスにする
例があったのですが
標準で存在する型に後から
独自の型のインスタンスにする事に違和感を感じ
バグの温床になるのではという懸念の印象がありました。
オブジェクト嗜好のサブクラスみたいに
「Int」型から「IntYesNo」型を
生成できるのなら違和感ないのですが。
これについての合理性と安全性を明示している
書籍やサイトを知っていたら教えて下さい。 >>381
温床とまで言うか・・・
そのせいで例えばどんなバグがありそうか、
ひとつでも例を示すことはできる?
ごく簡単な例でいいんだが。 >>381
あと、なんど読み返してもタイポっぽく見えないんでツッコミ入れる。
「AをBのインスタンスにする」と言うとき、
Aは型、Bは『型クラス』だからな。
失礼なことを言うが、もしかして違和感の根源は、
型と型クラスがそれぞれ何なのか理解できていないところにあるのでは? 『凄いH書籍』
(;・`д・́)...ゴクリ...(`・д́・;) 同モジュール(Haskellでいう)内なら拡張に対しては責任を持つべきなので
拡張がモジュールをまたがないなら大した問題はない
他の言語でもモジュール内操作に対してはあんまりフールプルーフじゃないしね
がHaskellの場合は拡張が子モジュールに伝播してしまう Ruby の偽は、false, nil の2つだけ!
JavaScript, Python, PHP などは、偽が10個ぐらいある!
空文字列・空配列・空辞書とか、0, 0.0 とか、
これらの言語は、しょーもないバグが多い!
だから、Rubyよりも生産性が低い! 『入門HASKELLプログラミング』2019年07月31日発売予定
https://www.shoeisha.co.jp/book/detail/9784798158662
「コンピュータのプログラミング」から脱却し、“学術”ではない、実用度重視のHaskell
入門書
Haskellは、関数型プログラミングを研究する対象としての側面が強すぎ、一般的なアプリ
ケーション構築を目的とした開発言語の側面が、ともすればおざなりになりがちでした。
そのため、他の言語(JavaとかC/C++とかC#など)がこなす、ありふれたアプリケーション
をHaskellで構築しようとすると、キーボードを叩く指が止まってしまうことがありました。
本書は関数型プログラミングの基本を押さえつつ、いわゆる「開発言語」として実用的な
プログラムを書けるようなレベルに誘う一冊です。(後略) >>386
rupy死んだのになんで生きてるの?ww
とっとと後を追いなよwwww Pythonのfalsyな値には、そんなに違和感はないけどなぁ……。 get programming with haskellは、stackがでてくるの終盤だったり、
あまり実用度重視じゃないんだけどなー >>389
Ture + True
みたいなのはエラーにしてくれたら良いのにとは思う ありがとうございます。
既存の型を独自の型クラスの
インスタンスにする事は
同モジュール内の拡張として
プログラムする人が責任を持つべきなので
問題はないとの事で了解しました。
急いで質問を書いたので
型クラスを型と間違って書いてしまいすみませんでした。 プログラム板にキチガイ降臨中!botに一晩も反応する異常さ
一般人(学校恩師)に殺害予告をしているのでスレ建て通報してください。
https://mevius.5ch.net/test/read.cgi/tech/1559872586/
142 名前:a4 ◆700L1Efzuv 投稿日:2019/06/18(火) 05:29:55 ID://qVkzO
>>141
名古屋の人な 俺ね、君の問題を大橋先生と混ぜないことにする。つまりね、
片桐孝洋のことをボコろうと思う。普通に顎の骨を折る。これくらいで警察来るか?
一般市民とかさ、普通にさ、俺らの秘密なんだけどさ、日本人なんて復活ねーから。 functoriality とはどのような性質のことでしょうか? >>397
補足しますと、functorial は分かります。
ですが、functoriality がいったい何に対してどのような意味で使う言葉なのか分かりません。
Hask圏を例にしてくれると助かります。 >>398
Functorであること
Haskellで言えば、Type -> Type なカインドを持つ型コンストラクタがFunctorのインスタンスであって、Functor則を満たすこと ラズパイでStackの環境構築をしていざコンパイルをしてみたら
・llvmは6.0のみサポートだよ
・一応コンパイルしてみるよ
というメッセージが出た後,
・サポートされていない機械語を使ってるよ
ということでコンパイルが通らなかった。
llvmを6.0のソースからmakeすればいいのかな?
Stackやllvmはすべてapt-getで最新版にしてあります。 officialのrepositoryと最新版(binary)は違うよ hackageのcabal-installのbootstrap.shをクリックしても
Page not found: Sorry, it's just not here.
とでてダウンロードできないのだが? >>401
レスありがとうございます。
公式の最新版とaptリポジトリでの最新版は違うということは認識してます。
やっぱり llvm 6 のソースを公式サイトからおとして make install ですかね? hackageのホームページのダウンロード数が出るところにはcabalとかからダウンロードしたものは
数にふくまれてる? 一応ラズパイ上(raspberian 9.4) でもコンパイルできました。
ただしstack を使わずghcで直接コンパイルですが。
オプションが渡されていないバグがあったような情報を
見かけましたがこのあたりが原因?
https://gitlab.haskell.org/ghc/ghc/issues/11058 3件もこのスレで本の省略系がアレでワロタ
協調させて省略するとこうなる
凄いH楽しく学ぼう この??の部分てどう書いたらいいですか?
f :: a -> IO (Maybe b)
g :: b -> IO (Maybe c)
h :: a -> IO (Maybe c)
h x = do
(y :: Maybe b) <- f a
(z :: Maybe c) <- ??
return z もっといいやり方ありそうですが、自己解決しました。
IO (Maybe)から、いったん MaybeT IO に迂回してからMaybe(Maybe c)を潰すんですね、、
import Control.Monad.Trans.Maybe
f :: a -> IO (Maybe b)
f = undefined
g :: b -> IO (Maybe c)
g = undefined
h :: a -> IO (Maybe c)
h x = do
y <- runMaybeT $ (MaybeT $ f x) >>= (\x -> MaybeT $ g x)
let
contractMaybe :: Maybe (Maybe a) -> Maybe a
contractMaybe aa = case aa of
Just (Just x) -> Just x
_ -> Nothing
return $ contractMaybe y Maybeを潰すのは型的に合っていないと思う
data A
data B
data C
f :: A -> IO (Maybe B)
f = undefined
g :: B -> IO (Maybe C)
g = undefined
h :: A -> IO (Maybe C)
h x = runMaybeT $ MaybeT (f x) >>= (\y -> MaybeT (g y))
h' :: A -> IO (Maybe C)
h' = runMaybeT . (MaybeT . f >=> MaybeT . g) >>413
ありがとうございます。
data宣言してるA B Cだと確かに型チェック通らないですね。
他にもa b cを具体的にStringにしたらダメでした。
a b cバージョンだと通ってるんですが、何か違いがあるのでしょうか?
また、実際とりかかっていたのは、
fが下のwebViewGetDomDocumentで、
gが下のgetBodyでした。
こちらもMaybeつぶしで型チェックは通っています(挙動はまだ確認していませんが)。
webViewGetDomDocument :: WebView -> IO (Maybe Document)
getBody
:: (DocumentClass self, Control.Monad.IO.Class.MonadIO m) =>
self -> m (Maybe Graphics.UI.Gtk.WebKit.Types.HTMLElement) h x = do {
y <- f x;
z <- case y of { Nothing -> return Nothing; Just y' -> g y' };
return z
}
なにがMaybe潰しだ
ただの分岐にデザインパターンみたいな名前つけやがって モナド則その2
m >>= return = m
を満たさない半モナド?を想定してる可能性 私は逆をお聞きしたいです
haskell の知識って圏論を理解する助けになりますか? Haskellと圏論を比較することでHaskellの過激な部分が見える
型を省略する
タプルでできることをカリー化でやる
「任意のfに対しgが存在する」ですむことを高階関数でやる タグつき共用体は簡単だ
C言語にもあった共用体をやめてコールバック地獄になったのはHaskellのせいではない 開発関係者の間で口コミが増えないから使われていないんじゃないか
消えるかもってことらしいがそもそも学術研究目的だからそれでも
構わないってことじゃないかと思うが… キラーアプリ(フレームワーク的な)でしょ
pandocでは不足 Pandoc 初版2006年8月10日 現在スター数 16,396
shellcheck 初版2013年7月24日 現在スター数 16,023
こういう感じのがもっとほしい そもそも数学の人気のなさをキラーアプリ説で説明できない
宗教では惑星の動きを説明できないみたいに オライリーの本にはパーサーは最強と書いてあるが何に使う?
まだパーサー必要じゃないので恩恵味わっていない パーサはオンラインサービスのやりとりの解析に便利そう。
あるいは溜め込んだビッグデータの解析前処理とか。 >>427
束縛という考えをやめたら人気は確実に出るかと
あれのせいで使いにくいわけだし 設定言語の Dhall にもパーサの強さが効いてきてるだろうね。Slackあたりで新しいキラーアプリみたいに言われていたやつ。
ただの設定より強いけどフルセットのプログラミング言語ほどでないために無限ループなどを作れず安全で便利らしい。
現在スター数二千弱 束縛あり
(m >>= \ x -> return x) = m
束縛なし
(>>= return) = id 関数抽象とかλ抽象とか内容にたいして意味がない説明が長々と続いてると思ったら
単なる無名関数のことだった
最初からそう書けばいいのにわざと理解が遠くなる書き方するのは何だろうね >>438
それはラムダ抽象などに興味がある読者を対象にしているからかもしれない。
単に説明が下手なだけかもしれないが。
ちなみに私は前者に当たるので、そういう単語が出てくるとワクワクし、理解がはかどる。 具体例を書けないやつは説明が下手なだけだし
具体例が長々と書かれていたら読み飛ばすようなやつは誤読するだけ
少なくとも動的スコープと静的スコープを間違えた例を書くべきだ
これに関しては数学よりも歴史が役に立つ >>442
> 具体例を書けないやつは説明が下手なだけだし
具体例を書けない人間は説明下手以前にそもそも十分に正しく理解していないからこそ具体例を書けないんだよ
中途半端な理解しかしていない人間が上手に説明できるはずがないだろうが
> 具体例が長々と書かれていたら読み飛ばすようなやつは誤読するだけ
具体例として長々としか書けないのも困り者だけれどね
説明する側が本当に良く理解できているならば、よほど高度にテクニカルで微妙な概念や定義でない限り
具体例としては簡潔で短い例や反例を挙げられるはずだ
> 少なくとも動的スコープと静的スコープを間違えた例を書くべきだ
> これに関しては数学よりも歴史が役に立つ
Lispの歴史が正にそれを物語っている
当時MITのAI Lab.のJohn McCarthyらによってLispがλ計算に基づいて初めて産み出された時、λ計算の変数のスコープを間違って
(というよりはLispが実装された1960年代前半のコンピュータのメモリ量と処理能力の極めて厳しい制限から)
動的スコープを採用して久しくその間違いを改めなかったのから、Guy Steele, Jr.らによるScheme言語の提案と同処理系の開発および
Lisp諸方言の統一化としてCommon Lispの言語仕様を策定する際に、変数のスコープとしてはSchemeの静的スコープを標準として採用することで
漸くLispプログラミング界で動的スコープでなく静的スコープが当たり前になったという歴史がね
ついでに言っておくと、かつてのLisp界隈での混乱として、言語仕様上の問題としての動的スコープ-vs-静的スコープの問題と
類似の(だが異なる)問題であるshallow_binding-vs-deep_bindingの問題(こちらは言語仕様でなく実装上の問題)とが混同されていて
混乱を招いていた(かなりしっかりしたLispの教科書でも後者を前者と混同して説明していたり、そもそもこれらの問題があることを理解せずに
書かれていたりした
shallow-vs-deepの問題が言語仕様でなく実装上の問題だと正しく且つ明快に言い切った(私の知る限り)最初のLispのテキストは
Lisp実装者だけでなく(当時の)Lispの上級プログラマにとってもバイブルとでも呼ぶべきJohn Allenの“Anatomy of Lisp”
と、まあ長々とした例を批判しながら、長々と書いてしまって申し訳ない 力が無いなら金で買えばいい
問題は、相手を説得したい者に課金するか自分を説得してほしい者に課金するか モナドから得た値ででかいレコード初期化したいときってなんかいい書き方ない?
do記法で左矢印で一々変数に束縛してからフィールドに代入とかするのめんどい
レコードワイルドカード使うのもアプリカティブスタイルで書くのもなんかいまいちだし >>448
Hoge { fuga =<< piyo }
こんな感じがいいなあ
レコードワイルドカードだと何してんのかぱっと見よくわからなくなるし
アプリカティブスタイルで書くとフィールドの順番変わったりしたときそれに合わせなきゃいけないのがちょっとだけ嫌 そもそも
b <- m
if b then ~
と書かなきゃいけない言語に贅沢言っちゃいかん ifはアプリカティブを使ってはいけない例か
意図的に書いてるなら頭いいな C++のnewも一個ずつだ
多変数関数の存在自体がバグみたいなもの レコードでなくMap型ならモノイドで足して上書きしていけるのに。 Haskellは数学者のおもちゃの域を超えてないな
実用を考えたらライブラリの豊富なPythonに勝るものはない >>456
> Haskellは数学者のおもちゃの域を超えてないな
本当の数学者はHaskellなんて相手にしないよ
Haskellという玩具で喜んで遊ぶのは数学者じゃなくて数学者にあこがれてるだけの単なるプログラマ じゃあ本当の数学者が相手にしてるプログラミング言語はなんなの? うちの大学の数学科の計算機系(論理とか統計とか確率とか)の教授はhaskellやってるらしい
あと数学科でやるプログラミングの授業はhaskellらしい おもちゃとは記号だったのか
記号などなくても実物だけがあればいいという
いわば実物指向 GHC8.8.1リリースされたね。ナガカッタ
stackで使えるようになるのはいつ頃か >>418
副作用の有る関数を、副作用の無い関数と同一視する仕組み(IOモナド)の論理的背景とかは理解出来るけど、理解出来なくても使えるしなぁ。。。
>>419
プログラマーが圏論理解するには手助けになるけど、それ以外の人には返って邪魔かも。 ああ!型システム入門─プログラミング言語と型の理論─が埃被ってる!
何年眠っていたんだ! 日系メーカで残業続きの日々です。C++を使っています。
Haskell覚えたらスマートな職場に転職するチャンスありますか? Javaでないだけマシでしょう
欲張っては全てを失います
胸を張ってC++コードを書き続けましょう でも所詮日系メーカでプログラミングの向上心持ってるやつなんて上司含めてほとんどおらん
そういう中で品質いいコード書く努力が虚しいんや まあたとえ誰も評価してくれなくとも
品質のいいコード書いておけばあとでデバッグやリファクタするときに自分が楽よ
Haskell覚えても転職に良いかはわかりませんが
C++の品質は多分上がる Haskellは一体いつになったら速くなるんだ
現状Javaにすら勝ててないじゃないか
関数型お得意の『最適化の余地』を永遠に残したままフィニッシュか!? こんな非効率な言語がPythonよりは速いって思われてる時点で最適化の賜物だろ >>475
call-by-valueのOCamlとcall-by-needのHaskellとでは実装法は大きく異なるから最適化技術も両者で大きく異なる
関数的プログラミング言語でもML系諸言語(OCamlやStandard MLなど)やSchemeなどのcall-by-valueセマンティックスに基づく言語の実装は
手続き的(あるいは命令的)プログラミング言語の実装にかなり近いし、例えば命令的言語では最も重要な操作である変数への破壊的代入や
例外処理を言語仕様に追加し組み込むことも特に困難ではない(実際、ML系諸言語やSchemeなどLisp系諸言語は変数への破壊的代入の
プリミティブを有しているし、Standard MLなどは例外処理も言語仕様に最初から組み込まれている)
だが変数への破壊的代入や例外処理といった言語機能をHaskellのようなcall-by-needセマンティックスの関数的プログラミング言語に
追加しようとすると途端にセマンティックスを整合的にすることが困難になる 既出ですかね
プログラミングHaskell第2版、いかがですか? >>478
買ったばかりでまだほとんど読めてないけど、教科書としてよさげ。
GHC前提になったし、古い記法は一掃されたし、分量も増えてる。
第I部はかなり平易な基礎と型クラスあたりまで。
第II部に対話系からモノイドまで持ってきて充実させてる。
ただ如何せん、出版社が弱すぎて、普通の書店になかなか並ばない。
ネット直販ならいいんだけどね。 東京だと
ジュンク堂や紀伊国屋でさくっと手に入ったけど
まあ普通じゃないな >>479 >>480
ありがとうございます
第1版は持っているのですが、なかなか良いものなので、増補されたのなら是非と思いまして
当該のサイトにも、池袋のジュンク堂にはあるとあったので、寄り道して購入しようかと… >>482
ページ数は1.5倍位になってるみたいだし、かなり増補されてたからさ 入門はすっとばしてLensとかConduitとか流行ったライブラリの実践例集みたいな本が欲しい
クックブックっていうのかね
なぜ出版社は入門書ばかり刷りたがるのか 入門はいいから初心者を鍛えてくれよ
将棋ウォーズでいうと3〜1級を初段〜三段に上げてくれる本がないよなぁ 並列並行haskellは面白かったな
英語苦手なのに無料公開されてた英語版全部読んじゃった 結局のところ、rigid type variable ってどんな type variable のことなの? skolem type variable のことだよ^^ >>484
取り敢えず使ってみよう勉強してみようという人間は多いので入門書にはそれなりの部数の需要があるが
実際に入門レベルをクリアしてその先に進む人数は一気に減少するから、その先の技術レベルの内容を扱う書籍は
よほどメジャーな言語でない限り商業ベースには乗らない
それも世界中がマーケットになる英語ならまだしも日本国内しかマーケットのない日本語の書籍となれば尚更ね 入門書はどうでもいいことばかり書いてるから買わないことが多い >>488
じゃあ、rigid = skolem なのか?
ghc のコンパイルエラーメッセージに
rigid で skolem な型変数がどうとか言う文言があるから、
両者は別物のような気がするのだが。
で、skolem とは何なのだ? >>491
rigid=skolemだよ
昔skolemとだけ表示されてたんだが、それじゃ分かりにくいというissueが立ってrigidが併記されるようになったらしい
俺もあれがなんなのか知りたい
俺としてはexists a. aみたいな型のことじゃないかと思ってるんだけどよくわからん
わかったら教えて >>492
なるほど、そういう歴史があったのか。
こういうのこそ、入門書に書いておいて欲しいな。 型aがMonadならApplicativeでもあるわけですが、
実用的にreturnとpureが異なるというのは有り得るのでしょうか? >>495
Monad版とApplicative版とで効率化のため内部実装が異なるということは
もしかしたらあるかもしれない(実例は知らないけど)
Monadが自然に誘導するApplicativeなら振る舞いが異なるということはないはず
(標準的なリストモナドに対するZipListみたいな話を気にしている) >>496
> Monadが自然に誘導するApplicativeなら振る舞いが異なるということはないはず
ありがとうございます。
安心しました。 モナドでアクションを繋げるってのは何がうれしいの?
参照透過のために仕方なくやってるだけ? みんなが使う言語の約束事が変更されるまで何年も待つか
一個人が関数を2つ定義するだけで解決するかの違い 同じことの繰り返しを書かなくて済むのが大きいかな。
例えばEitherとIOの組み合わせのモナドでハードとの通信を
書いた時,割り込みプロセスを考えなくてもLeftで返せば
後続コードを飛ばしてエラーを返せるし,コード量が減った
だけ,ミスの発生率も低くなる。
これがモナドなしだとハードとの通信をするたびにエラー
確認コードをいれて例外処理やなんやかやをしないといけ
なくなる。 EitherにもIOにもなるような万能のinstanceにロックイン?してよければclass不要
その気になれば任意の言語で応用可能ということ 結果的にHaskellの生産性は高いの?
ライブラリや学習情報の充実度を無視するとして 文字数が減るのは高階関数のおかげ?
参照透過性によるバグの低減やコーディングのしやすさはどの程度あるんだろうか? 巨大になっても線型に複雑度が増加するから他より有利とは言われるが
そこまで大きいの触ったことない PythonでもHaskellでも、タプルを使うなとか誰も言わなくなれば文字数は減る 文字数減ればいいってんならシェルスクリプトかperlが最適だな。 >> 505
モナドや高階関数のおかげもあるけど文字数が減るのは
つきつめると言語全体に貫かれた表現の簡潔さ志向の仕様によるかな
参照透過性のおかげで副作用を気にせず共通部分を
気軽に関数としてまとめられるとか
ブロック前後の括弧がいらないとか
再利用や多様な型に適合するように引数や関数の名前を短めにするとか
局所変数がないとか
簡単に二引数の演算子を記号を使って定義できるので
関数名を何度も書かなくて済むとか
いろいろ
書く部分が少なくなるとそれだけケアレスミスの入り込む余地は少なくなるね。
それとS/N比がよくなってロジックを追いやすい。 何冊か本を読んだけど、Haskell の気持ちがなかなか分からん… 何か書いてみた?
自分はRWHとかPCHとか読みながらオレオレプロジェクトを仕立てて
書き進めていったらある日を堺に急にこういうことかと理解が進んだ。 やはりどんどん書かないとダメですよね…
おかげさまで、本業とする言語でのコーディングには有意義なフィードバックができてはいるのですが
そもそも GHC が吐き出すエラーメッセージがなぁ〜 自分もエラーが何を意味しているのか最初はわからなかった。
ただほとんどのエラーは型の不一致由来。
だから何行目のどこでエラーが出ているかだけわかればあとは
型を順番に調べていって解決できるようになった。
スペルを間違えたり似たような目的で使う別の型と勘違いしていたり
とかそれなりの理由でエラーが出ているはず。後者は代数データ型を
適当にその場で作ったりしてた頃によくやってた。 LispとHaskellの間には謎の暗黒時代があるから
結果がすべての人にはそれがわからんのです その暗黒時代にSMLの本を店頭で見かけて気になった記憶がある。
結局買わなくていきなり普通のHaskellまでとんだ。
ソースから実行コードにどんなふうにおとしていってるのか最近
気になってきたのでそのうち古本でMLの本でも手に入れるか
GHCのが吐くコードを追っかけてみたい。 >>513
ありがとうございます >>512 です
皆さん同じような苦労をされているのかなと、少し楽な気持ちになりました
もう少し粘り強く取り組んでみます! どういたしまして!
基本文法は簡単だから文法エラーはすぐにほとんど出なくなります。
そこまでいったら初級編終了。 VIMで関数名にカーソル合わせると自動で型シグネチャ動的推論して表示してくれる機能ありませんか? ダイクストラのアルゴリズム
優先度付きキューの手作りから始めて一週間かかってやっと完成した
あたまわーるわるわーるーわる〜♪
sm32181836
脳裏に流れてる 善意的に解釈してアルゴリズムの方の動画だと思ったが
案の定あたまわるい方の動画だった practical haskell second edition読み終わった Haskell Wiki
!haskellwiki
Hayoo
!hayoo
Hoogle
!h
Hackage
!hkg
Hoogle at Stackage
!stackage
https://duckduckgo.com/bang?c=Tech&sc=Languages+(Haskell) アマゾン.co.jp
!ajp
https://learning.oreilly.com/home/
!orly
O'Reilly
!oreilly >>510
mylist 3 = [[1,2,3],[4,5,6],[7,8,9]]
みたいなリストを作る関数をHaskellで作ってみれば関数脳に目覚める。
割とマジで。
Haskell入門以前って電子書籍で書いたが、自力で目覚めるなら買わなくても良い。
(Haskell入門書読んでも宣言的とは?関数脳とは?がピンと来なかった経験から書いた) パッと思いついたのはこんな感じ?
添削してくれたら嬉しい
HaskellでなくPureScriptだが
mylist :: Int -> Array (Array Int)
mylist n = do
i <- 1..n
pure [i*3 + 1, i*3 + 2, i*3 + 3] >>525
コメントありがとうございます!
>>510です
ひねりなしですが…
mylist :: Int -> [[Int]]
mylist n = chop n [1..n^2]
chop :: Int -> [a] -> [[a]]
chop _ [] = []
chop n xs = take n xs : chop n (drop n xs)
chop は、直近に読んだ書籍からそのままアイデアを拝借しましたが、カンニングなしで書きました
[1..] のように、無限リストで書けたらと思いましたが、酒気帯びなためダメでした
IO の純粋って、のようなことがサッパリです… >>527
うーん・・・。
貴方はまだ手続き脳ですね。
(その手順でも関数脳を実感する人は実感するのでしょうが)
罰としてHaskell入門以前をご購入下さい。
IOの純粋は、「プログラマーのための圏論」と言うPDFがネットにあるのでググって読んでみると良いです。 (n: number) => Array.from(Array(n).keys()).map(
i => Array.from(Array(n).keys()).map(
j => n * i + j + 1
)
) >>528
>>510です
では、
mylist :: Int -> [[Int]]
mylist n = take n (chop n [1..]) >>528
>>510です
コメントをつけ忘れましたが、ご紹介いだいた圏論のレポートは、以前にちょっと目を通したことがあったと思いますが、サッパリだった記憶が…
あらためて拝見します
ありがとうございます! >>530
ちょっとchopと[1..]から離れましょう。
そして、[1..n]に何をすれば次のリストを得られるか考えましょう。
プレリュードの(入門以前と書かれた通り)基本関数の組み合わせだけで書けます。
IOと言うより入力ですが、関数の引数か、外部からの入力かだけで中身の処理は普通の関数と同じと捉えましょう。
そうするとreadLine関数が部分適用で見た目の引数の減った普通の関数に見えて来ませんか?
圏論で謳っているのは、どこから来たかが違っていても同じ事をするなら、同じ関数と見なそう。
そう言う、ある着目点以外の差異を無いものとするという事です。 >>510 です
mylist n = take n $ f [[1..n]]
where
f [ns] = ns : f [g ns]
g ns = map (+3) ns
としたところで、要素に f を繰り返し適用して無限リストを作る関数があることを思い出し、思い出せずにカンニングして iterate を発見
mylist n = take n $ iterate f [1..n]
where
f ns = map (+n) ns
map (+n) 辺りがどうも… 間違えた、先の関数の (+3) は (+n) でした 文字数が減る主義を粛清した結果がこの関数脳内革命なのか?
文字数が減るでよかったのに 競プロでもあるまいしアルゴリズムを非直観的なものに変形させる必要がどこにある?
そんなに漸化式が好きなら iterate (\xs -> [last xs+1,last xs+2..last xs+n]) でもやってろ プログラミング運算やると計算量がオーダーレベルで変わるよみたいな話もあるから
非直感的な宣言をすることがいつも無駄とは限らないだろう
今スレで話題になってる例が教育的によいかどうかはわからんが 効率的な計算量になるようにコンピュータが計算して最適化してくれたらいいのに なにしてんの
mylist n = [ [(m - 1) * n + 1 .. m * n] | m <- [1 .. n] ]
とかじゃだめなの ただでさえO(n^2)なのにiterateとかやったらO(n^3)じゃん mylist n = take n $ chunksOf n [1..]
がダメらしいからそれもダメなんじゃない?知らないけど >>537
7000円
>>533
手続き型言語をやっていると非直感的ですが、そうで無い人(プログラミング未経験含む)だと割とこっちもメジャーなので、こっちが浮かぶのが関数脳を作れた基準?にしてます。 n個の品物が入るナップサックがn個あって
1,2,3...と番号の書かれた品物を順番にいれていく
等々いくらでも行動的比喩が可能な問題に対して数式的に考えることが自然ねぇ・・・
まあ人間の思考傾向を議論するつもりはないけど
少し考えればシンプルに解ける問題は少し考えろと主張をしたいんだとしても
我々手続き的ゾンビにとってmylistの例が「直観性」を犠牲にするほどシンプルだとは思えないけどね チューリング完全なもの同士は等価である
Haskellと他の言語が等価であることを直感的に表現しているのがモナドだ
この文脈ではモナドが直感的だと思わない奴の直感はあてにならない
プログラミング未経験者ってのは文脈無視するのを正当化するための道具にされてるだけだろう モナド=単一子=世界の究極の根本要素
でもHaskellのモナドは外部とのやり取りを隠蔽してる脇役みたいなものでしょ 無理やり型合わせするためだけの言い訳だな。
くっだらねーとしか思わんかったわ。 そう思ってでもまだこちらをのぞいているってことは
かなり気に入る・気になる部分もあったんだよね。
どんなところがよかったの?あるいは気になったの? CSで使われる用語って何かのめたふぁか知らんけど
無理に数学に合わせて造語っててかえって判り難さが増すというね モナドが分からんという人が多いのは
哲学のモナドと混同してるからだろうな
全く無関係の別物だと理解する必要がある モナドはわかっても何が凄いのか全然わからん教えてくれ 哲学と数学の違いは「嘘を言ってはいけない」という点にどこまで集中するかの違い
すごいものを作るより有害なものを作らないことをどのぐらい重視するか たしかにモナドすごいすごいって言う人っていざ説明させると説明できないよねw
せいぜい受け売り止まり >>560
俺は話聞いてるだけ
強引なHaskell推しに困ってる モナドほどの抽象化しただけで画期的じゃん
イテレータとか用意してデータ構造によらないコンテナへの共通インタフェースとさらにそれへの特別なシンタックスシュガー用意した言語ぐらいならあった
モナドなんか用意してdo記法なんてシンタックスシュガー用意してプログラミング言語における手続き的処理やその他諸々を抽象化した 抽象化できてるか?
手続き型と同じっぽく見えるけど、いざ活用しようとすると同じようには使えなくて意味不明な型エラーで詰まる
結局のところモナドの仕組み理解できてないと使いこなせない
これは抽象化できてないってことでしょ そりゃ任意の手続き型言語を再現できるわけではないから完全な抽象化ではないけど
手続き型的な処理とか、失敗する可能性のある処理とか、非決定的処理だとか、そう言った諸々をまとめてモナドとして一般化してる
そのおかげでそれら全てで共通にdo記法やモナド向けの関数といったものが使えて、各種毎に個別に関数を用意したり覚えたりする必要が減る
自作のDSLなどを構築するときにも
モナドインタフェースを実装するだけでdo記法やモナド向け関数群を使えるようになる
他言語でDSL構築は結構大変だし、オレオレDSLなんてどういう仕様かわかりにくいけど、haskellなら型から検索したり型を見たりすることでどういうアクションがあってどうやって使うのかがわかる これがC++だったらJavaScript環境を作ってC++の仕組みを隠蔽するかもな
Haskellでも同じことをする自由はある 関数脳になるとどんな利点があるのかな?
手続記述は使い回ししにくい?
参照透過性が確保されていて型の情報があれば
算法の記法が手続き的か定義的かを問わず
どちらでもいいような気もするが >>551
Haskellのモナドって関数型で命令的な処理の書き方をしたいってことだろ
要するにLispにPROGフィーチャー入れたのと同じような動機だろ コンストラクターがオーバーロードできないから別の列挙型に同じタグ名がつけれないんだけど
どうしたらいい? >>569
学び始めはそう理解したが bind 演算子とか融合とか進んで
現時点では切り分けや共通化の便利な道具と思ってる >>576
俺も一瞬それ思ったけど同名データコンストラクタもできたっけ? data 宣言を別モジュールに分けて
両方が必要なら import ... as ... で別名をつけるって方法はどう? モナドを導入することで副作用のない
「副作用のチェーンをつくって渡す。」
ちなみに実行は副作用させるというバカみたいなレトリックを実行してるだけ。
バカはそういうものをありがたがるんだよ。
そしてそういうものをありがたがるというのはバカみたいに本質なんだな。 >>575
Haskellは個人の趣味・自己啓発の道具の範疇なので
参考にならないでしょうが…
名前がかぶるのはどこか機能がかぶってたりするかなと
型の使い方を見直したり組み合わせる関数を見直したり
所属するモジュールを移動したりとか。
どうしても名前がかぶるってときは英語名や日本語名
ときには中国語とかも借用する(ただし英字を使う
ローマ字やピンイン表記)か密接に関係する事柄の
接頭辞をつけてる。 >>580
モナドで副作用・副作用もどきを扱えるけど
モナドの全てが副作用・副作用もどきを伴う
わけではないでしょ。
リストもMaybeもEitherもモナドとして扱う
定義はされているが別にそれをつなげても
副作用があるわけでなし。 非決定計算やIOが同じモナドというククリで実現できるのが大変興味深いです なぜそんなにお前らがモナドについてあーでもないこーでもないと話し合ってるのかがわからない
モナドなんていたってシンプルな考え方なのに
モナドなんて単純にどうやって関数を合成するかというルールにすぎない
より正確には、「モナディックな関数」を合成するルール
では、モナディックな関数とは?それは"装飾された値"を返す関数のこと。
どんな装飾が施されたかについては、文脈によって様々だが、たとえば…
・エラー -> 失敗を表すデータもとりうる値 MaybeとかEither Error
・非決定性 -> いくつもの値を同時に表す値 List, Array
・副作用 -> 副作用自体を表すデータ Effect, Aff
・状態を扱う -> 状態を表すデータとセットになった値 Reader , Writer, State シンプルな考え方合成ルールといいつつ
肝心のルールの中身を説明しないで
利点や応用分野のみ紹介する
典型的な日本人話法
モナドは単なる自己関手の圏におけるモノイド対象だよ。何か問題でも? いやだから装飾のされ方は物によって様々だって言ってるじゃん
ルールの中身も当然装飾のされ方によって様々なんだから画一的に述べられないってわからないか?
一つ言えるのはbindとpureの定義を与えるってことくらいだが
あるいは同値な定義だが、関手であることを要請した上でjoinとreturnを与えるのでも構わない
数学者のモナドの定義を述べているお前ならこっちのほうが好みかもな 「自己関手の圏」の中身を説明しないからわけがわからない
関手の合成は積?
恒等関手は単位対象だが終対象ではない?
うっかり始対象になったりしたらそれ積じゃなくて和じゃないか 自己関手の圏におけるモノイド対象としてモナドを理解することは、必ずしもプログラミングのためになるものではないから必須ではない。
それでもそれを理解したいのであれば、プログラミングの文脈で理解するのではなくて、ちゃんと圏論の文脈で理解した方がいい。
Bartosz MilewskiのCategory theory for programmerがわかりやすくておすすめ。 【僕用メモ】
・bind と pure の定義を与える
・関手であることを要請した上で join と return の定義を与える
両者は同値である。 だめな理系人間の特徴
初学者に対してひたすらwhatを説明
だいたいコミュ障を併発してる >>593
そうでもなくね? っていうか内容がHaskellに関係なかったw お前らって圏論なにで勉強したの
英語の本読んだの?大学の授業とかで習ったの? 知らん用語が出て来るから初学者で戸惑う人が多いだろうが
内容は小学生でも理解出来るレベル Basic Category Theory, Tom Leinster
英語で読んだ >>595
数学教室 πの焼き方と、プログラマーのための圏論。
ただ、読んだ後に意味を吟味して閃きが必要だった。
まず普通の関数とモナドな関数を同じと見做す考え。
IOモナドの入力は基本、文字列を受け取るので数文字列を受け取って、整数に変換後2倍する関数を作るとする。
getLine >>= \s -> return $ 2 * read s
これと同じ効果の普通の関数を作ってみる。
getLine’ s = 2 * read s
このgetLineとgetLine’をそれぞれ部分適用で見かけの変数を減らす形に変形。
getLine >>= return.(2*).read
getLine’ = (2*).read
この場合、2つの関数は型と引数からの入力か入力装置からの入力かしか違いがない。
関数の中身から見れば、いつ、どんな文字列が来るか分からない。同じ数文字列が来たら同じ結果を返すと言う意味では同じと見なせる。 そして、圏論の主張は変数は引数無しの関数でも有ると言う事。
以下は関数である。
f x = 2 * x
しかし、部分適用されたカリー化関数は関数でもあり、変数でもある。
f = (2*) (関数でもあり、関数という値を返す変数でもある)
すなわち、x = 1のようなただの変数も、つねに1を返すxと言う引数の無い関数と見なせる。
x = 1 (1と言う値の入った変数であり、常に1を返す引数無しの関数でもある)
Haskellでは表現できないものの、さらに言えば数そのものも圏論では値であり、変数であり、関数である。
単純に書くと以下の通りだが、
1 = 1
ペアノの公理(ペアノ数)を使った方が概念的に分かりやすいかも知れない。
data Nat = Zero | Succ Nat
1 = Succ Zero >>590
youtubeにある彼のビデオレクチャーも良いよ モノイドのところがよくわからんかったけど読み物として面白かった
https://chrispenner.ca/posts/wc >>604
ちょっと待て
モノイドのところが一番の肝で面白い部分だろ >>601
>数そのものも圏論では値であり、変数であり、関数である。
もしその様な表現が可能な拡張がされた場合何が起きる出来るんですか?
数値に新規の型を設定して値で変数で関数みたいな扱い出来ないかな 圏論うろおぼえだけどそれって圏論の範疇だっけ?
圏論ってマッピングする理論であってその対象が値か関数か変数か関知しないのでは?
値が関数ってのはラムダ計算から来るものでしょ
確かにそれらを組み合わせて計算理論になるわけだけど >>601
お前が圏論を全く理解していないことは良くわかった
圏論には「関数」とか「値」とか「変数」といった概念はない
「対象」と「射」との2つの概念があるだけだ
だからお前の次の
>数そのものも圏論では値であり、変数であり、関数である
これは単なる間違いさえ通り越して全くのナンセンス
圏論には値も変数も関数も存在しないのだから
何を対象として何を射とするかは個々の具体的な圏によって異なる >>608
ああ、ちょっと簡単に書きすぎたね
確かに関手 >>609は書いてる途中で間違って送信してしまった
>>608
ああ、ちょっと筆(じゃなくてキーボード)が滑って簡単に書きすぎたね
確かに関手とか自然変換といった概念も圏論にはあるが、これらもある圏から見れば射や対象に過ぎない
いずれにしても圏論には値や関数や変数といった概念はない では何らかの制限がないと取り扱いが難しいよね
例えば英語と日本語の翻訳で使われる意味を咀嚼変換するロジックを圏論だと言われたら
なんか凄く難しそうだなとか 別に集合論だって写像の集合を考えればいいわけでそんなのは圏論を持ち出さなくても十分
重要なのは圏論は写像の合成(関数合成)を抽象化して扱う理論だということで
だからこそa -> IO bを射とする圏を作れればそこでの射の合成方法は普通の関数合成と同じように扱える
で実際にIOはクライスリトリプル(Monadのインスタンス)を定義できるからa -> IO bを射とするクライスリ圏が定義できる 質問です。
当方数学科卒で学生時代圏論は死ぬほど使ってました。
しかしアーベル圏という純数学的なお話知ってるだけで、計算論に応用する話は全く勉強した事ない状態です。
そういう人間が圏論の計算論への応用を勉強したいときオススメの教科書、参考書は何かご存知ですか?
抽象圏論や数学基礎論も少しかじった事があるのでその手の話が出てきてもあまり困る事はないと思ってます。 そこまで圏論に詳しいなら逆に世の中の有象無象の情報処理の実態を
見て新しい提案ができるんじゃないかと思うけどどう? 型推論とモナドがわかったら解散でいいじゃん
だらだら続けるとサンクコストが増える 浮動小数演算みたいなある種のモナド則が成り立たんものを考えると、
逆にモナド則のありがたさがわかる。
そんな程度で十分だよ。 浮動小数点のモナド?
モナド則の結合律っぽい奴は普通の関数で言うなら
f (g x) == (f . g y) x を要請してるのであって
f,gの計算には依存しないから浮動小数点が破壊することはないよ ミス f (g x) == (f . g) x だった f x = x / 0.3
g x = x * 0.3 ghci でやってみたら循環小数にならなかった。macOSの電卓でも。
へぇ〜。 >>613
> そういう人間が圏論の計算論への応用を勉強したいときオススメの教科書、参考書は何かご存知ですか?
> 抽象圏論や数学基礎論も少しかじった事があるのでその手の話が出てきてもあまり困る事はないと思ってます。
理論計算機科学(以下、TCSと略)への圏論の応用を勉強したいのならば、最もベーシックなテキストとしては
1. Andrea Asperti & Giuseppe Longo: Categories, Types, and Structures, 306+xii pp., MIT Press (1991)
型理論として単純型付きλ計算と2階の型付きλ計算それぞれに対する圏論的意味論を議論している他、
型無しλ計算の意味論を展開する上で不可欠な再帰的領域方程式とその解に対する圏論的な見方も解説している。
更にHaskellなどで喧しいモナドやKreisel圏についても解説している。(関数プログラミング言語へのモナドの応用は
本書の著者の1人であるLongoの論文から全てが始まった)
この本の最大の欠点は誤植がとても多いことと昔のMacで書かれていてテキスト中の数式も図も美しくないことだ。
なお、現在は書籍としては品切れになっていたと思うが、著者のHPから電子的に無料で入手可能になっていたはずなのでネットで探して下さい。
2. Roy L. Crole: Categories for Types, 335+xvii pp., Cambridge University Press (1993)
様々な型理論(型理論は(関数)プログラミング言語とその型システムを形式的体系としたものと考えて良い)に対する圏論的意味論を議論している。
3. 横内寛文:プログラム意味論,261+vi pp.,共立出版 (1994)
久しく品切れになっていたが少し前に増刷されたので現在はジュンク堂などの大型書店などの店頭で買えるはず。
表示的意味論、型無し・型付きλ計算、領域理論、関数型言語の意味論について1つずつ章を設けて解説した後、この本で必要とする圏論の解説がされ、
プログラミング言語の表示的意味論で必須の再帰的領域方程式とその解法に対する圏論からのアプローチと
λ計算の意味論としてλモデル・λ代数・圏論的モデルとしてのCCC(デカルト閉圏あるいは積閉包圏)について解説している。
この他にもTCSへの圏論の応用としてはオートマトン理論への応用や代数的仕様記述言語の意味論への圏論の応用
(こちらの意味論ではデカルト閉圏は使われない)などがある。 >>622訂正と補足
まず1に関する説明中の次の箇所を訂正します。つい筆が滑ってKleisliをKreiselと書いてしまった。
誤> 更にHaskellなどで喧しいモナドやKreisel圏についても解説している。(関数プログラミング言語へのモナドの応用は
正> 更にHaskellなどで喧しいモナドやKleisli圏についても解説している。(関数プログラミング言語へのモナドの応用は
それから、
> なお、現在は書籍としては品切れになっていたと思うが、著者のHPから電子的に無料で入手可能になっていたはずなのでネットで探して下さい。
と書いたが、無料の電子版は著者の一人であるLongoの次のURLよりPDFファイルの形で配布されている。
https://www.di.ens.fr/users/longo/files/CategTypesStructures/book.pdf >>618
浮動小数においては
(a+b)+c != a+(b+c)
なんだよ。 >>624
だからこそ「モナド則の結合律のこと言ってるの?あれは関数合成的な話だから関係ないよ」
って言ってるんだけど
ああもしかして>>616は結合律一般について言ってるのか?
それならアスペみたいなこと言って悪かった
いやまさか四則演算の結合律の便利さから
printFile file = readFile file >>= putStrLn
printFile == readFile file >>= putStrLn
になることの利点を理解しろという主張だとは思わなかったからさ・・・ いやモナド則で語ることなんて結合律以外ないだろ。。
結合律を無条件で仮定できる状況がどれほど負担を減らすかって話なんだが
ここまでバカな絡まれ方するとは思わなかった。 ああ、printFile file == readFile file >>= putStrLn だった
しかもそれも誤解しか生まない表現で
要はreadFile file >>= putStrLnをprintFileで置き換えても問題ないってことを言いたかったんだけど
いやほんと5ch向いてないね >>626
いやほんと頭が悪くて申し訳ない
「足し算の結合律って便利でしょ?モナド則も結合律だから便利なんだよ」
こんな糞みたいな主張をする人間が世の中にいることぐらいは分かっておくべきだった >>629
前提として「足し算の結合律って便利だね」
じゃ足りないの
何が不足なのかな
副作用をモナドの結合連鎖外に及ぼさない事による恩恵が主目的じゃないの?
とくにマルチスレッドコア環境だと色々有難いよね
モナド連鎖の組み合わせとか組み替えとかがスカッとできてイイ!とか
連鎖の中で起きたエラーのリカバリーとかはよくわからん >>631
モナドが実際の所どれぐらい便利なのかは分からないけど
(m >>= f) >>= g == m >>= (\x -> f x >>= g)
が言ってることは単純なんだよ
>>=が普通の関数呼び出しのように使えるというだけ
$(普通の関数呼び出しを演算子化したもの)の場合を考えれば分かりやすいかな
g $ (f $ x) == (\y -> g $ (f $ y)) $ x
関数と値の引数が$と>>=では逆だから両辺が逆向きになってるけど
要するに二つの関数を一つの関数まとめても構わないという
誰もが当たり前にやってることの理論的基盤を>>=にも要請してるというだけなんだよ
だから getLine >>= printFile と getLine >>= readFile >>= putStrLn
が同じだと言うためにはこの結合律を満たさなきゃならない
ちなみに二個以上の関数をまとめ上げる場合や多引数の場合もこれで証明できる >>632
モナドの条件が成立すると色々便利な事は認識している
端緒の認識はそれで問題ないと思ったけど
便利だよねって見解が
>こんな糞みたいな主張をする人間が世の中にいることぐらいは分かっておくべきだった
って言われて、え?え?何かマズイ理解なり認識があるのか??
何がマズいのかワカラン??って感想
単純に罵倒してマウント取りたかっただけなら問題ない >>624見たとき何言ってんだコイツと思ったが案の定ボコされてて安心した
論理的な思考ができない人間って怖いわ >>624
>浮動小数においては
>(a+b)+c != a+(b+c)
>なんだよ。
まるめ誤差を考慮すればだけど
浮動小数点を引き合いにだして!=だってやった事か >>633
そこは売り言葉に買い言葉だったんじゃねーの。
俺は雑な主張はアリだと思うし、それに対する善意の解説もいいと思うぞ >>633
三段論法的なのが糞だって言ってるだけでその部分は別に間違ってないよ
まあマウンティングするつもりはないんだが
曖昧なこと言っといてそれについて意見したら「バカに絡まれた」なんて
そりゃ感情的にもなるよ確かに大人げないけどさ >>636
そう言ってくれるなら嬉しい限りだけど
最初のレスから反省する点が多すぎるのでもう消えます
スレのみなさんご迷惑をおかけしました😿 まあかなり意地の悪い例を出したつもりではあったけどね。
「論理的思考」とか言い出す輩が引っかかりそうな例を。 どうでもいいけど「論理的アルゴリズム」だったら簡単にコピーできそう
アルゴリズムとパラダイムの違いの一つは、コピーする自由 モナドの話してる中で一人結合則全般についての話始めて浮動小数点数に関する当たり前の説明せっせとしてんのは草
小学校で習う掛け算も足し算もモナドみたいに便利だけど浮動小数点数はモナドと違って不便だねえ 最近近隣スレで浮動小数点数で恥ずかしい書き込みを繰り返してる香具師を観かけたが
きっとCS知らない浮動小数点数覚えたての厨房が暴れてるんだろう 素人なので確認したい
浮動小数点演算は計算式の組み替えによって生じる
計算ごとの丸め誤差とその蓄積が一意ではない
そこが問題。でいいですか? 例えば、3桁の有限桁数で、
123,000 + 987 は、どうなると思う?w >>644
浮動小数点は実装の有効桁数とか精度誤差の複合なんですね
やっと理解できたとかも >>644
>123,000 + 987 は、どうなると思う?
合成や結合則との関係は? ヒント
(123000 + 987) + 456
123000 + (987 + 456) >647
有効桁数3の条件下では
443
443
で結合則?を満たしている >>647
ヒントなどと気取らず最初からその例を出せばいいのに…
>>648
整数計算で有効桁数という考え方はあまりしないとおもうし
計算途中の有効桁数範囲外の取り扱いを決めておかないと
なんとでも言えるような。JISにあったかな? >>649
最初からも何も最初言ったの俺じゃないし誰でも気づくだろ 最近のHaskellは末尾再帰形は当たり前として、余再帰形まで最適化するってマジ? モナドの話すると怒る人が一定数いるのに
最適化の話は難解でもすんなり受け入れられるのなんでだろう >>653
モナドとか関係なくあまりに馬鹿っぽいレスが怒られるだけ
例えば>>653もそう 年寄りが自分の理解できないことをしゃべるなって
いっているだけでしょ。最適化はなんだかんだいっ
て実践もしくはなんとか理解できる範疇とかでは。 例えば「馬鹿っぽい」の定義はモナドの定義よりもずっと複雑なんだよ
そのわりに「馬鹿っぽい」は難解すぎるという認識はほとんどない Haskellや圏論のモナドってライプニッツ由来?ギリシャ哲学由来? モナドの場合、「俺の理解は正しくて、お前の理解は間違ってる」てな話になりがちだから。 >>622
お返事おくれて申し訳ありません。
時間作って是非挑戦みたいと思います。
ありがとうございました。 【ぼくようメモ】
Haskellはマルチディスパッチをネイティブサポートしているので、
デザインパターンの一つ、Visitorパターンを気づかない内に使っている。 Haskellを勉強するとどんなメリットが有りますか?
@ Haskellを使って仕事する開発プロジェクトなんてものは世の中に有るのですか?
A @が無いなら開発プロジェクトが無くても仕事の効率化などで、役立てる方法は有るのですか?
B Aも無いなら、勉強して得た知識を日々のJava等の開発プロジェクトで役立てる方法は有るのですか? 3かな。
コード書く際に
入出力部分と、ディターミニスティックな部分を選り分けるような書き方するようになった。 >>661
世界に目を向ければ、Reddit でよく求人されてる >>662
>ディターミニスティック
??
基本遅延評価なので即時評価とのより分? >>664
ディターミニスティック
決定論的な
IOが絡む非決定論的なコードと、引数と戻り値の関係が決まっている決定論的なコードとを、
しっかり分けて書けるようになったと言いたいのだろう。
要するに、副作用のあるコードと純粋なコードを分けるということだ。 皆さんありがとうございます。
どうやら、あまり勉強する意味がなさそうに感じました。
なぜみなさんはこの言語をおやりになっているのでしょうか?
趣味でしょうか? まあ勉強する意味はないといえばないかな。
その当時盛り上がったってのが理由だったりするから趣味といえば趣味。
でもまあその言語がどういうところを気にして作られたかってのを
触って実感するってのはプログラム全般で役に立つと俺は思うけどね。 Javaから初めて、Javaしか書いたことが無い人というのは再帰メソッドとして実装した方が良いものも、慣れていないし面倒くさいからという理由で再帰にしたがらない傾向が有ります。
Hakellを勉強した人間なら、そういうことが起こらないという利点が有るといいうことでしょうか? ループより再帰がいつも正しいわけではないでしょ
Javaなんだし
おれが仕事でやってるプロジェクトでは再帰は基本NGだよ haskell学んでも、stack safeな再帰を書けるようになるわけでもないから、
haskellを学ぶ利点だとは思わない
理由を探さなきゃ学ぶ気になれないものには手を出さなければいいんだよ
CSの世界に限っても死ぬまでに学びきれないだけのネタがあるんだし 『達人プログラマー』でも「毎年1つ新しい言語を学べ」と言っている
まあ凡人にそこまでは厳しくとも
たまに新しいプログラミング・パラダイムに触れることは
プログラマーにとって有益であると思うよ
それは知識として即効性のあるものというよりは(そういうのもあるかもしれないが)
1年2年経って効いてくるタイプのものかなと >>661
Aかな
宣言的プログラミングの作法が身につく
普段Javaを使っているのなら、
最近のJavaは関数型プログラミングのシンタックスがかなり増えてきているので
Haskellで高階関数の使い方を理解しておくと、Javaプログラミングに直接的に役立つ 横レスだけど、そんなに役に立たないものなのか...
入門本買おうか悩んでたのに >>665
副作用ですか
Cのポインター辺りは副作用上等でトリッキーな事をしつつ記述してあるわけで
副作用と脆弱性に苦しんだ結果、RUST
Haskellの恐ろしい所はプログラムが何らかの高度な数学的アルゴリズムな場合があって
別途資料がないと全く理解できない
あっても以下略 >>670
プロの世界では振り飛車は居飛車より勝ちにくいと言われますが、久保九段や菅井七段のようにそれを使って実践で勝つプロもいます。
アマの世界では振り飛車か居飛車かが直接勝敗に結びつくような高度な戦いができないので好きな方を選べばいいです。
ところが、ビジネスプログラミングの世界ではどうでしょうか?
残念ながら、手続き型プログラミング言語の開発プロジェクトしか存在しません。
関数型は使おうにも使う場所が無いのです。 >>679
Javaだって宣言型にシフトしつつあるし、
最近のJavaScript(ECMAScript)は基本的に宣言型プログラミングだよ
宣言型プログラミング=関数型プログラミングではない 宣言型を変にもてはやす記事とかあるけどさ、
あれバグがあるときに凄まじくデバッグしにくいってことはちゃんと知っておいた方がいいぞ。 >>682
それはいくらなんでもド素人すぎるだろう >>683
多分、君は論理プログラミングとか制約プログラミングについて理解してないんだろう。 >>684
むしろそちらの方が専門に近いのですが、
どういうことか教えていただけますか? >>674
>『達人プログラマー』でも「毎年1つ新しい言語を学べ」と言っている
新しい言語を一年に一つ、とは、これは厳しい縛りですね… >>679
>久保九段
地元の棋士なので光速谷川氏とともに密かに応援してたりします >>685
横からだけど
凡人にとっては数学的な静的な関係を見つけ出すのはしんどいことが多い
副作用あろうが、ソースコードをステップ実行でトレースできる手続き型の方が
問題解析が楽ってことは往々にしてある >>686
ジャンプ漫画みたいな台詞すこ
「三つか四つはないと、暇を持て余してしまいます……」的な モナドって結局、計算効果Tをもたらすプログラム(T-プログラム)は
クライスリ圏をなすからクライスリトリプル(モナド)がT-プログラムの
合成規則として必要だから出てくる >>691
否定しないが結論としてはそうだぞ
モナドを利用したテクニックと登場する理由は違って当然じゃね? >>681
>Javaだって宣言型にシフトしつつあるし
どのような店を持ってシフトしているとおっしゃっているのか、例を教えていただけると嬉しいです。 モナドの副作用云々は
Scala Monix の並列プログラミングも面白い >>678
恐ろしさというよりも
Haskellの仕様その他聞くと全く関係ない数学の話をしだす奴ばかりでカンファレンス途中で抜けてきたことがある
数学には全く興味ないんだがね
言っても聞きやしないこいつらとは合わないわと思った >>695
マジでHaskellは数学者が数学者の為にデザインしたみたいなものなので
ネット上のコードも数学的専門性に全振りしたものが普通にある
そんなのは数学の専門課程と無関係な人間には理解できない
だけど、英文の赤黒木を扱うHaskellのコードは恐ろしくスッキリ短くて
余分なノイズが少ない
全体の把握が楽だった、恐ろしく高密度かも
コメントで書く詳細説明≒Haskellのコード 型の宣言だけならコードの中に埋め込むことはできた
だが数学の知識をすべて宣言するのは無理
だからコードを読みながら数学勉強しようと思ったら、わかることは静的型ばっかりだぞ
そもそも数学は広大過ぎてどこから手をつけるか迷うから静的型から始めるのは合理的 数学の後ろ盾があるとよくわからない安心・万能感を錯覚し
これがよくわからない人を呼び寄せてしまう
この魅力はオカルトめいている
謎多き異性に惹かれてしまうのと似ている >>696
>赤黒木を扱うHaskellのコードは恐ろしくスッキリ短くて
>余分なノイズが少ない
赤黒木がそんなに短くなるのですか?!
やっぱり haskell をがんがらなくては オカルトめいているのは数学でも言語でもない
人間の感情がオカルトめいているのだ >>700
英語の参考資料(ブラウザで翻訳しつつ
Red-Black Trees in a Functional Setting
ttps://pdfs.semanticscholar.org/7756/16cf29e9c4e6d06e5999116f777e431cafa3.pdf >>702
thx a lot !
英語は読めないのですが、想像していなかったくらいに簡潔ですね… PostgREST は Haskell のキラーコンテンツになれるか Haskellの代数的データ構造は、速度が低い方に引かれるけど、恐ろしく合理的な手法かも知れない
中身は基本Lispの構文糖衣相当だからLIST処理のコストがそのまま処理速度に反映される
ただ、数学者が数学者の為にデザインした分だけ優れた表現力をもっている
C++で
class TEST {int a, b, c}; が
Haskellでは
Test Int Int Int になって
関数の定義時に
add (Test x y z) =
z + y + z
関数定義で型指定と値を変数名に拘束して計算する
test = Test 1 2 3
add test
なんか凄い気がする Simon Peyton Jonesもなんかよくわからんけど関数型言語カッケーと思ったからやった
って言ってるくらいだからそういうのでいいんかもなとは思う。 >>705
C++17なら、そこそこそれっぽく書けないか?
struct Test { int a, b, c; };
auto add(Test t) {
auto [x, y, z] = t;
return x + y + z;
}
auto test = Test{ 1, 2, 3 };
add(test); おっと、型定義はこっちのほうがそれっぽいか
#include <tuple>
using Test = std::tuple<int, int, int>; C言語のswitchとenumが貧弱だったせいでコールバック地獄が始まったわけだが
コールバックの一部を、代数的データ型の場合分けで代替できる
数学者のためのデザインとの指摘はあたらない >>707
同意します
C++の出力コードが速い事も
ただ、アルゴリズムとデータ構造を表現する時Haskellのコードがスッキリしてる
Haskellで組んだOSの例も HaskellでOSを作るプロジェクトがある
Haskellそのものがガベージコレクションが必要なLispの構文糖衣的性格があるので
通常のOSはGCを利用するではなく、必要であればGC的メモリー管理もしますな立場
Haskellのそこら辺の拡張を無理やり行ってとりあえず動いてますと言う体裁だそうです
LispでOSを作ればシステムの軽さ速度に制限が起きることと同じです
一応これ
Haskell OS
ttp://programatica.cs.pdx.edu/House/
見解の元ネタに近いもの
Can a operating system be made completely in Haskell?
ttps://www.quora.com/Can-a-operating-system-be-made-completely-in-Haskell そういえば随分以前にLISP専用プロセッサを開発したっていう
大学があったなぁ。 その成果は同じく遅延評価があるTCLに結実したんですか。
三十年たっていると若者の人生相談にのってあげたりしないといけないですね Haskellは世界を救うってセミナーで言ってたけど。 みずほのシステム移行にHaskellが採用されていたなら半年で完了できていたって言ってたよ。 >>719
その手の話よく聞くけど
なんで、こうも関数型は人気ないん?
F#も人気上は微妙だし セミナーでは数学の素養が足りないからだって言ってたけど、僕はもう手遅れなので、次世代に期待してます。 数学自体は結構勉強したけど 圏論のよさはよくわかんね
ある意味数学の分野で一番かもしれない、圏論のよさが分からんのは
次はホモロジー代数かな
代数幾何は一番時間食ったけど、理解できていないので除外するけど >>720
さすがにそれは言い過ぎ
単にコンパイラを通せただけだ パタンマッチの要素不足やらリストの範囲外参照やら
STMの糞詰まりやらいろいろ実行時エラーの要素は
あるよね まあ少なくとも、意図した型じゃないのに実行できる上、そのまま実行時に死ぬことすらしない言語よりはよっぽどマシ
(ちょうど今、某動的型付言語でハマってキレてた) >>719
COBOLのソースをHaskellで組んだプログラムで解析して
全体の処理、依存関係資料を作成
それを参考にしつつ java他へ移行じゃなかったけ?
詳細はググってください
COBOLのコードはトリッキーな記述はしない素直系だから解析はかどるんちゃう? >>723
英語読めない人が、英語のよさがわからんというのと同じじゃね
あなたが読めるものに誰かが翻訳してくれるのを待つか、
あなたが読めるようになるか
代数幾何なんて圏論で再構築されているから圏論の言葉がわからないと
どうしようもないけど、ホモロジー代数まで有用さがわからないというのは
代数が向いてないのか、興味が隔たっているのか微妙なところ >>721
関数型パラダイムの、ユーザ向けの簡単な部分のいいとこどりは各言語でされているし、
人気もあると思う
それを超えて関数型言語に入ろうとすると、面倒くささのほうが勝っちゃうのかも
F#は、実行速度が遅かったのも大きいと思う RISCとCISCって本当に2方式独立してんのか
圏論って複素解析を婉曲的に表現してんじゃないのか?
アイレンバーグは4元数も研究してたしバーコフ息子は流体力学研究してた CPUレベルで実は関数型言語に翻訳されてたら
数学的に解析しやすいし高速化も数学的にできるしバグも数学的にとれる
という妄想をするんだが
失敗の歴史をウソと考えると 現行の半導体プロセッサはスイッチングで起きる0と1状態を基本にして組みあがっている関係で
他の技術(量子関係?)が発達しない限り関数的内部表現うんぬんはLISPが誕生した時点で完了してます
テキストベースの文字列を実行可能なコンピュータプログラムに変換する行為は
文字、テキストベースである限りLIPSの構文糖衣と見なせます >>721
カプセル化の恩恵を受けられないからかと
Haskell含む関数型はは仕組み上データを分離/隔離できないのでロジックに比重を置きすぎてるきらいがある
一般的にはクラスに任せたい、内容を知らなくても扱える構造が欲しいわけで
関数ドリブンではやはり困る
個人的にはCに逆戻りしてる印象すらあるね ブライアン・カーニハンもf#の中間言語は
解析しやすいCであるべきだってプロジェクト立ち上げれば
関数型といいつ中身は手続き型でデバッガの資産も使い回せるから
人気でるかもよ。 Cに逆戻りしている・・・型安全とガベコレがあるCを作ってしまったのか モジュールがあるからカプセル化の恩恵は受けられるのでは >>741
でもまさに内容を知らなくても扱える構造だぜ? カプセル化「継承とポリモーフィズムがやられたようだな・・・」 カプセル化: 抽象データ型、pattern synonym等
継承: クラス継承
ポリモーフィズム: 存在量化によるサブタイピング多相
haskellってストラウストラップの言うOOP言語なのでは >>729
横からですけど、ホモロジー代数の有用性を教えてくれませんか?
何に使えるんです? >>745
コホモロジー全般を抽象的に取り扱える。 >>745
俺もまだあやふやなんだけどどうも複素解析で積分するとコーシーの積分定理みたいに
純トポロジカルに積分値決まるじゃん
どうもモチベーションはそこらへんで
複素平面だと複素解析の教科書みたいに簡単にいけるけど
複素多様体上で線積分しようとするとややこしいからざっくりややこしいところを
ホモロジー代数って分科したみたい ポアンカレから来ているし本当に突き詰めるとたぶん複素解析力学の問題解けるんだと思う >>747
代数幾何の教科書に層とコホモロジーが載ってるけどそのあたりと関係するのかな
>>748
難しそうだね >>732
> 圏論って複素解析を婉曲的に表現してんじゃないのか?
的外れにも程がある
層sheafは解析接続の考えを多変数複素関数へと拡張する発想で生まれたものだが
圏は複素解析から出てきたものではない >>720
エアプ乙
空リストにheadしちゃったらあっと言う間やん >>745
ホモロジー代数の有用性...
代数系の多くの分野の主力ツールなので知らないと入門書を終えた後に代数系で先に進めない
くらいには使われています。直接使われていなくてもやってることはホモロジー代数由来の
ことがよくあります
古くは、ホモロジー代数の枠組み(コホモロジーなことが多い)で完全列が見つかると
機械な計算だけでいろいろな結果が出てくるというのが強みでしたけど、その後は
ホモロジー代数の枠組みにはまらないものを一般化したりして新しい枠組みを作って
ホモロジー代数のように扱えるようにしてきて多くの分野が生まれています。
derived categoryやtriangulated categoryもそうですし、環論のquasi-frobenius ring
(入門書にある森田の定理の延長)などもこの線
自分で圏や代数構造をつくるのでなければ圏も代数も知らなくていいと思いますけどね Haskellって素晴らしい土台造りの研究に終始して、中々家を建てない印象 もう立ててあるんだろ。MSのpower shellも当初はモナドシェルという
名称だったけど無関係だとは思えない haskellってほんのちょっとしたものにも名前つけなきゃいけなくて困る 素晴らしい世代別GCの研究はする
でも今作ってるアプリは参照カウントで十分
こういうとこだろ >>753
なるほど
層とホモロジー代数という本でも現代数学の多くの分野の記述に欠かせない重要な基本言語であると言ってますから
そういうことなんでしょうね
ありがとうございました 型シグネチャちゃんと書いとけば、後はポイントフリーにしてお茶を濁して、利用者が命名してねって感じに逃げることも可能 HKD(Higher Kinded Datatype)ってのはな
おまえら例えばコマンドラインツールのオプションとかを扱うとき
Options <$> ... <*> ... みたいにしてデータを返すアクションを構築してるだろうけどさ
そこの ... 同士に共通性があるわけじゃん。
コマンド引数>環境変数>設定ファイルの優先順位で読み出されたりするじゃん。
でも各フェーズごとの処理をまとめるのはこのままじゃ難しいわけよ
ところが方針を変えて、中身と外見がひっくり返ったような
data Options_ f = Options _ { verbosity :: f Int, ...}
を使うとエントリごとに Nothing にしたり出来るようになって、
Options_ を一般化したやつらが Generic 介しておんなじように舐められるから処理の共通化もできて、
値の合成もしやすく、コンパイラの warning でエントリの処理漏れを検知できて、いいよね。
このパワーアップしたデータみたいなもんを高カインド・データ(HKD)って呼ぶぞって話 コマンドオプションを無駄に複雑にしないように設計に時間使う方が有意義。
てかオプションごとき糞みたいな複雑な解析いれるくらいならすべて設定ファイルにしろよ。 なーる。多変数Maybeでコマンドレットか。
getoptにs付けるか付けんかとかいみなかったんや >>764
オプションを上書きできないと不便だし、
ツールごとにどんなに設計しようと不可避の複雑さは残るだろうさ。
HKD使えば複雑な解析にはならない。
https://chrispenner.ca/posts/hkd-options
ちな Options から Options_ を Generic で作るやつもある
https://github.com/i-am-tom/higgledy いや普通に作ってればそんな複雑にはならんわ。。
無理やり用途を探してるってのはわかるけどさ。 >>768
そうかな。改善前と同等の機能のコードをもっとシンプルに書ける?
個人的にはさらにリッチに、設定値が原因で問題が起きた時「設定ファイル〜のここで定義された値が原因でコケたよ」
くらいのことも言ってくれると嬉しい。HKD に Writer を突っ込んだりすれば出来る。 https://www.stepup-school.net/news/detail/728
微分方程式と圏論と量子コンピュータやるっていうけど
こういうところで圏論という言葉が出てくるの不思議な感じがする >>770
> こういうところで圏論という言葉が出てくるの不思議な感じがする
圏論は現代の数学を記述するための言語だから、ある程度以上のレベルの数学を教えようとすれば圏論という言葉を学ぶのは避けられない
ちょうど、現代では英語という言葉を学んでおかなければ数学や自然科学で重要な研究論文を読んで学ぶことができないようにね だから自由ソフトウェアとか割れとかを宣伝して商品は宣伝しないスタイルがある PostgREST は Haskell のキラーコンテンツになれるか 結局代数幾何やらずに圏論語っても胡散臭いものにしかならん。
別に代数幾何がすべてとはおもわんが起源ではある。 集合論と集合の圏が胡散臭い
だったら射はあっても冪はない圏などを考えれば胡散臭さは軽減される気がする >射はあっても冪はない圏
集合論を取っ払うなんてことは圏論は望んでねーわ。
馬鹿すぎて話にならん。 馬鹿を取っ払いたい願望があるとはっきり言い切る方が簡潔で良い 私代数幾何ではありませんが数学科で代数系で圏論バリバリ使ってました。
しかし計算論への圏論の応用という意味ではほとんど役に立ってません。
圏論はその表現力の高さゆえにほとんどの数学に登場します。
しかし逆に言えばその登場の仕方で全く別の顔で出てくるのである一つのジャンルで出てくる圏論を極めても他ではほとんど役に立たなくなる事は多々あると思います。
まだ計算論で出てくる圏論の勉強は始めようとしてるとこなので代数幾何に出てくる圏論がどの程度役に立つかは断言はできませんが、あまり期待はできないと思います。 型はフェイクではない
○○を応用した成果が型である
ゆえに○○はフェイクではない
このように「応用」や「成果」の概念がフェイクに加担している >>780
> CSに出て来る圏論はフェイク
CSとCSでないとの境界は曖昧なわけだが
例えば構成主義的な型理論などはその典型だ
少なくともBart JacobsのCategorical Logic and Type Theoryでの型理論はCSでなく数理論理学で
そこで出て来る圏論はフェイクでなく本物だと思うがねえ
Lambek & Scott (Phil)とそこで出て来る圏論に関しても同様
だからこそ数学を基礎付ける枠組みとしてのHTT (Homotopical Type Theory)などという考えが出てくるわけで
逆に言えば代数幾何で出て来る圏論は間違いなく本物なのは事実だが数理論理学で出て来る圏論から見ると酷く偏った部分だけだし
逆から見れば数理論理で出て来る圏論は代数幾何の圏論から見れば同様に非常に偏って見える
最近の高階圏や高次元圏の隆盛を見てもわかるとおり圏論の可能性は極めて広く豊かだから
「××で出て来る圏論はフェイク」といった主張はナンセンスだよ
ただ、本来、数学を知らずに使えねばならない単なるプログラミング言語に過ぎないのに
「圏論がどうした、モナドがどうした」、といって圏論を勉強しておかないとプログラムを書けないかの如く喧伝するのは
フェイクというか一種の羊頭狗肉あるいは虎の威(圏論、あるいは純粋数学という一種の高級ブランド)を借りる狐(プログラミング言語という実用道具)であり
間違った姿勢だとは思うけれどね そうそう
多言語との差別化、マウント
選民主義の道具
あるいは原理主義で貫いてますよという言い訳みたいなもの
圏論必須みたいに言うのはバカ とはいえほとんどのプログラマが欲しいのはどうせ虎の威だろ。
だからこの業界は何の発展もない。 >>784
そう
僕らは「正しく」後追い根性から抜け出さなければならないと思うよ
そこから抜け出せないから日本はIT後進国 PostgREST は Haskell のキラーコンテンツになれるか 動的型付け原理主義なら権威もないしダメージもないんだが
ノーダメージな選択肢を冷笑して程々のダメージ受けてるやつもそれはそれで難儀な性格だ まあ権威が言ってんだからで済ましたり静的チェックしてるから大丈夫とか
言い聞かせる方が地道にベンチマーク取るよりよっぽど楽だからな。
結局はそういうことだろ。
言い訳をしたいんだよ。 >>787
REST API作るのは他言語でも簡単だし、いまさらRESTっていう気もするし、
これだけで使ってもらうのは無理筋 rubyをいくらdisっても構わないと思うが
disるだけじゃ何も産まれないからな 反日パヨク野党にはほめるところもすきなところも何もないわ 誰だよそいつは
自分を匿名化するのは別にいいけど敵を匿名にするなよ >>793
>野党
は言語なのか?
はじめにことばがあった。ことばは髪とともにあった。
ことばは髪であった。
というくらいだから気になるかしらんが。 何が問題のある機能か語る方がプログラム技術は向上する。
好きなものだけやってるバカは働いてほしくない。 技術自体が目的になることを問題視する風潮なので
サイコパスですら手段の目的化には強い罪悪感を持つようだ
もはやサイコパスでもなんでもないただの人 apiサーバー実装としてhaskell結構いけるという話が出てるな。
ちと興味出てきた。
モナドガーとかずっと言ってるバカしかいないのかと思ってたがそうでもないようだ。 圏論流行っているのって、人工知能の機械学習の理論のベースが複素多様体(複素ファジー)
にあってアルゴリズムに落とし込むにあたってバッチリ実学になるからとかそういう理由から? haskellの真価は機械学習で出るとかそういうやつかな。勝手に納得くっそー。 FRPの金脈は掘り尽くされてみな失望して出て行ったの?
Haskellでゲーム作りを通してFRPを学べるみたいな本がLeanpubで書かれてたけど
作者途中で断念しちゃったんだよね 慈善事業で地位向上やってたんだろうが。ちくしょう。 くっそ。こんな頭に線繋いで文意の通らないコミュニケーションとれるとか。
公認基地外化してなんてやろうだ。
邪魔するつもりはないが、全国クイズ大会とかいつまでやるつもりだ。 >>802
圏論の流行の理由はそっち方面とは全く関係ない
一つは関数型プログラミング言語の型の体系の理論的基盤である型理論が圏論と直接的な繋がりがあるところから
もう一つは実用プログラムとしては避けて通れない例外処理や状態の概念をHaskellのような関数型プログラミングで扱うための理論的基盤としてのモナドから 関数型言語設計者にとっては重要だとしても、
Haskellを使っている人にはどうでもいい理論ってことか。
>>圏論 アリアドネーの糸か蜘蛛の糸か。
でもどのみち結論はゼロサムだろう。 arrayパッケージのData.Array.! は配列に O(1) の計算量で参照できるのでしょうか? >>811
よく考えたら、IOモナドではないので、O(1)で参照できる配列構造を作れるわけないですね。
質問は無かったことにしてください。
くだらないことでスレを汚してしまい、すいませんでした。 命題
IOモナドではない ⇒ O(1)で参照できる配列構造を作れない
を証命せよ 我々は副作用は使ってないっ!キリッ
完全にクリーンなプログラムを書いているのだ!キリッキリッ 色々なコホモロジーの同型の証明については圏論は力を発揮するが、
型理論においてはそういう風にも考えられるよね?以上の意味はない。
単なる箔付けだな。 doは単なる構文糖だな
それで、Pythonのlambdaの仕様を変える必要がないことが証明されてしまった
これだけでも十分大きい >>817
一つの型理論に対するモデルは原理的に様々なモデルがあり得る
その様々なモデルをまとめて特徴づけるのには圏論が便利なんだよ
いわゆる圏論的モデルだよ
圏論的モデルというのは本来の(数理論理学での)意味での具体的なモデルでなくて
与えられた理論に対するモデル全般が満たすべき性質の圏論による公理化とでも言ったほうが良い感じの代物だからね
それと型理論に応じて圏論モデルとしての圏には特有の興味深い構造(例えばデカルト閉圏とかモノイダル閉圏とかね)を持つケースが多い >圏論的モデルというのは本来の(数理論理学での)意味での具体的なモデルでなくて
>与えられた理論に対するモデル全般が満たすべき性質の圏論による公理化とでも言ったほうが良い感じの代物だからね
なるほど、数学基礎論の方面をあんま知らんからそういう発想になるわけか。 いわゆる同型を除いて一意的(up to isomorphism)なモデルなことではないか。
どういうものかはわからんが。 もうよElixirやろうぜElixir
Haskellに近いコーディングパターンマッチングも出来るし
もう、色々ユルユル
非同期マルチスレッドプログラムで受け手がないのにメッセージ送り捲れる(メール形式なので)
割り当てメモリーを使い切るとエラーで止まるけど(メールボックス満杯)
もう、ユルで目からウロコ メールボックスがオーバーフローしない証明しながらコーディングするんすか? メールボックスだから受け手のプログラムも起動して非同期でメッセージを受け取って
メールボックスから消せばOk.
通常はメッセージの送り手スレッドがメールボックスの空き待ちになるだろ
メールボックス管理は独立したスレッドで動くんじゃね?
とにかくユルイ
僕でも出来たヽ(^o^)丿な感じ ライブラリーのソースコードをレビューしてるWebサイトってありますか?
この書き方は秀逸だとか、これは泥臭いとか
バージョンアップでのコードの進化を追ったり
英語でも全く構わないのですが Windows 10 64bit 上で FFI (ccall) 使って Haskell の関数を呼び出してて
呼ぶ前に hs_init() が必要なのは,なんとなくわかるんだけど
hs_exit() の方は,そのあとアプリケーション全体がすぐ終了する場合は
呼ばなくてもいい?
Windows が呼び出し元のプロセスも Haskell ランタイムも開放してくれるよね
hs_exit() 呼ばなくても。たぶん
この辺,わかる人いますか プロセス切り離せば?
そうでもしないと他言語呼び出しなんて低レイヤーデバッグする覚悟ないとやってられんぞ。 やってられない理由は低級言語でもHaskellでもなくGHC
Haskell実装はGHC以外にもいくらでもありえるから >>832, >>833
なんか GHC の FFI は
入っちゃいけない領域みたいに思えてきたんだがw
まぁたしかに,DLL で組み込むよりは別で組んだほうが
デバッグは圧倒的に楽だよね
(Rust でも DLL 書いてるけど,めちゃくちゃ苦労してる 計算のキャッシュをしたい。
ある重い計算 heavy :: IO Char があってそれを f,g :: IO () から呼び出す。
一度 heavy が呼び出されて Char が返ってきた後はそれを使いまわしたい。
f で呼び出したなら、その結果の Char を g でも使う。
ただし heavy の実行は f,g のどちらかが呼ばれるまではしたくない。
cachedHeavy = unsafePerformIO heavy
とすれば cachedHeavy が利用されたときに一度だけ簡約がおこなわれて、
その時だけ heavy が実行されるので、これを使えば事は足りる。
でもなるべく unsafe は使いたくない。どうすればいいでしょうか。 何もしなくても最適化で一回しか使われなくなるんじゃないの
haskellはそんなに馬鹿なの? >>837
ターミナルからの入力 readLine みたいにキャッシュしたくないときもあって、
上記のような値を普通に呼び出すコードからは、コンパイラは意図を判別できない。
>>838
なんぞそれ -- cached :: IO a -> IO (IO a)
main = cached heavy >>= \ cachedHeavy -> 云々
こういうのでいいならunsafePerformIOは不要 >>840
はい。 f,g はトップレベルではなくIOアクションの中で定義しても大丈夫です。
IORefを使わなきゃ無理かな、と思ってたんだけど、これは目から鱗でした。
cached = pure
でいいんだよね?単にモナド一枚かぶせるだけで計算のキャッシュになるなんて、
今年一番のオドロキですわ >>841
cached = pure ではない
IORefを使うのは正しい >>842
うーん指摘の通りだった。
>>841 のやり方ではIOアクション cachedHeavy を簡約で実行した時点で heavy が計算される。
f や g の中でそれぞれ実行したなら都度重い計算が走ってしまう。
i <- cachedHeavy をその前に実行するなら一度で済むが、遅延の要件「f,g のどちらかが呼ばれるまではしたくない」
を満たさない。 つまり… こんな感じでいいのかしら
cached :: IO a -> IO (IO a)
cached f = do
r <- newIORef Nothing
pure $ do
c <- readIORef r
case c of
Nothing -> do
ts <- f
modifyIORef r . const . Just $ ts
pure ts
Just ts -> pure ts
> x <- cached $ print "heavy" >> pure 42
> x
"heavy"
42
> x
42 >>845
間違っているところがあったら、具体的に教えていただきたい。 cabalファイルの中でexectableで同じcabalファイルの
ライブラリー名をbuild-dependsにかいてあるのに
そのライブラリーのbuild-depensを全部書かないとコンパイルできない
のはなんで?テンプレート使ってるからとかある? ソースディレクトリをexeとlibに別々にしたら直った
なんだこのバグは酷いバグだ 岡部健 (Ken Okabe)今度はQuoraでもアカウントBANされる
https://link.medium.com/EX3Y4COIs2 キャッシュ? https://wandbox.org/permlink/98ZKnQW0uSr5c5CV
f () = print "hoge" >> getLine >>= \x -> print "foo" >> return (\() -> x)
main = do
putStrLn "1234"
f () >>= \g -> do
let e = g ()
print e
print e >>852
たしかに f で行なった計算の結果を g で使えてるけど、俺の求めてたのは
さらに g の結果も f で使えることなんです。どっちを先に実行しても計算は一度だけ、を求めてた。 そもそもライブラリを全てimportする奴はいないので
使わなかったライブラリのコードは最後まで実行されない
全てのライブラリについて使うか使わないか予測できないならば実行の順序は予測できない >>854
ここにいるぜ。まあ可能な限り、ということだけども…
多すぎでリンクできなくてGHCが落ちるのが面白かった。 え、岡部健ってQuoraで暴れてたの?
アカウント停止はまた癇癪起こして名誉毀損してたとかが理由?? >>856
彼がなにかしらのコミュニティーでうまくやっていけないのは、これまでの活動からわかりきっている。
むしろ、Quoraではよく持った方だと思うよ。お薬をきちんと服用するようになってるんだろうね。 haskell自体はいいんだけどstackとかhieとかいちいちでかくてめんどくさい
本当にhaskell書いてる人はいるの? 依存関係を管理するのは理想
依存関係を消すのが現実
C++やSTLに依存することすら嫌ってCだけで書くみたいな現実 実際にHaskellでコード書いてみると分かるけど
コンパイル通れば計算結果は確かに正しいんだけど
巨大なメモリを謎に使うようなバグが混入する事が結構あって
その種類のバグってエラー吐かないから特定がめっちゃ難しい。
巨大なプロジェクトでHaskell使うのは現実的には無理だと思う。 それ
haskell で書かれたプログラムのパフォーマンスチューニングむずすぎる あればあるだけ使おうとするんでない?
足りなくなってからようやく(これからやる処理に必要最低限の)ガベコレ
この繰り返しだから永遠に自転車操業 この種のバグの混入原因って大抵の場合
ネットに散らばっている'Haskellらしい'記法にあったりするから
初心者の頃に読んだ書き方が
「(実はこの人全然Haskellでコード書いてないじゃんっ!!)」
と気が付くまでワンセット
ネット上だと処理が大きくなると破綻するようなサンプルコードばっかりでウンザリする
特に遅延評価を活用するような記法は
大抵メモリ関連のバグの原因になるから実際には避けなきゃダメなのばかり デフォルトの挙動性格評価にするやつあったよね
あれ使ってる? ガベコレ言語を全否定してみるのも一つの方法
たとえばスマホが壊れたら全部新品にするかそれとも壊れた部品を特定してそこだけ修理するか 結局最適化しようとするとコンパイラのくせをしっかり理解してたり
凄まじい技術力がいるという。。 Rustってhaskellerにも結構評判いいけどどうなの >>871
俺は「あぁ,Haskell でいうアレね」みたいな感じで学べた
厳密な感じが好きなら,気にいるんじゃないのかな
ドキュメントも揃っていて学びやすいと思う
ただ,俺はいまいち使い所を見いだせてない
Haskell で書ける分野なら Haskell で書いちゃうし
ちょっとしたツールとかサーバーサイドとかは Go のが楽だし
WebAssembly を生成するために使うのが
今一番,Rust の活きる分野な気がする
Rust は,クロスコンパイルが楽なので
(個人の感想です >>871
ただのLisp方言やML方言はもう飽きたってことだろ 「C言語は純粋関数型」と言ってたのってQuoraの岡部健? フロントをrustで書くとか一番馬鹿な選択だろ。話にならん。 もしかしてParsecってあんまり使われてない?
Parsecのドキュメントが2001年とか古いのしか無くて、最初のサンプルコードすら通らない
ライブラリの使い方が解らなくていきなり躓いてる ここの住民、圏論とかの話だと玄人っぽいのにプログラミングの話になると初心者っぽくて謎 >>876
ドキュメントと言うのが何を指しているのか具体的なURLを示してくれないと、
何が原因でどう躓いているのか、助けようにも調べる取っ掛かりが無くて困る。
あと、本当にその古いドキュメントとやらしか学習資料は無いのか?
他にチュートリアルやブログなどは参考にならないのか? どうせ躓くなら一番最初に躓く初心者っぽい奴の方が運が良い
ビギナーズラック
巨大なメモリを使う巨大なプロジェクトの完成直前に躓くのはかなり運が悪い ここ[parsec: Monadic parser combinators](http://hackage.haskell.org/package/parsec)に載ってる
これ[Parsec, a fast combinator parser](https://web.archive.org/web/20140528151730/http://legacy.cs.uu.nl/daan/download/parsec/parsec.pdf)です
他のは、ついでにParsecに触れているという感じで、詳しそうなのはこれしか見付けられませんでした
<続く> 最初のサンプルコードをGHCiで打ち込んで試そうとしてるんですが、
Prelude> module Main where
Prelude> import Parsec
<no location info>: error:
Could not find module ‘Parsec’
Perhaps you meant Parser (needs flag -package-key ghc-8.6.5)
モジュールが見つからないと言われます
最新バージョンの名前空間?と明らかに違っているので、
ここ[Text.Parsec](http://hackage.haskell.org/package/parsec-3.1.14.0/docs/Text-Parsec.html)で、この二行
import Text.Parsec.Prim
import Text.Parsec.Combinator
を見付け書いたところ
Prelude> import Text.Parsec.Prim
Prelude Text.Parsec.Prim> import Text.Parsec.Combinator
<続く> Prelude Text.Parsec.Prim Text.Parsec.Combinator> simple :: Parser Char
<interactive>:6:11: error:
Not in scope: type constructor or class ‘Parser’
Perhaps you meant one of these:
‘Parsec’ (imported from Text.Parsec.Prim),
‘ParsecT’ (imported from Text.Parsec.Prim)
Prelude Text.Parsec.Prim Text.Parsec.Combinator> simple :: Parsec Char
<interactive>:7:11: error:
? Expecting two more arguments to ‘Parsec Char’
Expected a type, but ‘Parsec Char’ has kind ‘* -> * -> *’
? In an expression type signature: Parsec Char
In the expression: simple :: Parsec Char
In an equation for ‘it’: it = simple :: Parsec Char
Prelude Text.Parsec.Prim Text.Parsec.Combinator> simple :: ParsecT Char
<interactive>:8:11: error:
? Expecting three more arguments to ‘ParsecT Char’
Expected a type, but
‘ParsecT Char’ has kind
‘* -> (* -> *) -> * -> *’
? In an expression type signature: ParsecT Char
In the expression: simple :: ParsecT Char
In an equation for ‘it’: it = simple :: ParsecT Char
引数が足りないみたいなことを言われます
英語も怪しいのに英語の解説も使えないとなるとどうして良いやら… haskell ide engine って今どんな使用感?
そろそろ spacemacs haskell layer (中身 intero) から乗り換えようと思ってんだけど
未だにバージョン 1 未満なのが気になった。まだ待つべきかな。 >>880
おお、ありがとうございます
そっちでやってみます >>877
クヌースなんかもそんなもんだぞ。
プログラム理論と実装ガツガツやる能力は別物だから。 >> 883
このエラーメッセージ
Not in scope: type constructor or class ‘Parser’
これは Parser が見つからないよ。みたいな意味
検索サイトのフーグルを「パッケージ指定」機能を使って探すと
https://hoogle.haskell.org/?hoogle=Parser%20package%3Aparsec
Parser は import Text.Parsec.String すれば使えるってことが解って、
同じように letter の場所も調べられる。
attoparsec や megaparsec にも似たやつあるっぽいから、何となくで読み替えていけばいいんじゃないかな。 >>886
> クヌースなんかもそんなもんだぞ。
Knuthはそんなことはないだろ
TeXもMetafontも最初のはKnuth自身が実装したのだから
> プログラム理論と実装ガツガツやる能力は別物だから。
圏論なんかの知識は実装と全く関係ないからね、そういう方面に明るいのと実装能力とは全く無関係だ KnuthやLinusって
圏論どころかカプセル化・継承・ポリモーフィズムすら使ってない印象がある
実装能力とは全く無関係だし >>889
は?
そんなの日本の組み込み現場の奴らの大多数と同レベルじゃん 何をもってknuthにスキルを疑うのか分からんのだけど、彼のプログラミングスキルが
ゴミクズな世界があったとしても、scratchから書く問題ならアルゴリズムだけで
他の人より速いもの書いてそう 本人がtex書くまでこれほど大変と思ってなかったいうとるやん。
そのあとの文芸プログラミングとか、cのコード見てても、これあかんなとしか思わんわ。 Haskellは小さいプログラムを作るには最適なんだけど
大きいプログラムになるとメモリ周りの最適化が困難なのよね
実行結果自体は正しいからテストすり抜けるだろうし
バックエンドで採用しても
本番環境で初めてメモリヤバイと気付いて死ぬ未来しか見えない >>897
最初に上がってたsigmaの記事を発見したぞ
https://engineering.fb.com/security/fighting-spam-with-haskell/
なるほどHaskellを実運用するコツはGHCの魔改造から着手する事なのか
・・・って真似できるかーい!! >>898
ノリで採用したら地獄を見た感がヒシヒシと伝わってくる記事だね
その後facebookでHaskellを採用していない事実で察し
https://livedoor.blogimg.jp/sag_alt/imgs/7/e/7ece2698.png 遅延評価を諦めて型システムとパターンマッチ系統だけを
よくわからないけどCとかC++辺りに持っていくじゃだめかな 赤黒木のコード読んでいたら
関数の定義に型情報があるけど
型推論で処理されるコード部分には型情報がない
目視で定義ーコード部を交互確認すると結構きつい
抽象化には貢献してるけど、人間が読み下すのは大変、オレはコンピュータじゃない(怒
そんな感じ 要件定義が整っている関数の書き下ろしと
プログラムで記述されたコードの読み下しは難度が異なる
Haskellのコードは情報密度が高い事と抽象度の高さが強烈に効く Hakellだしコード読めば分かるだろ(コメントなし)
↓数カ月後
俺の書いたコードなのに意味が分からない・・・ 工学と名のついた無根拠な宗教が蔓延ってる言語よりは科学してるだけマシ >>905
次の日とか
その日のうちでも
意味が分からなくなることがある 赤黒木は左右対称のコードを2回書かされるから書きたくない
コードを読まなくても分かる
読む前から分かることをどれだけ知っているかが重要
読み始めてから努力するのは遅い >>909
よく読め、受賞は2019年だが
受賞内容は2009年の功績の話だぞ
そこで語られてる内容も2014年のGHC魔改造の件の話だし
5年も経過してるのに未だにその話しか出てこないって事はそういう事よ よく読んだら分かること
読まなくても分かること
普遍的な方を重視するのがいいと思うよ ちなみにFacebook自身は2015年の投稿で2年かけて
Sigmaの主要技術をHaskellに移行したといっている
https://engineering.fb.com/security/fighting-spam-with-haskell/
スライドもある
http://multicore.doc.ic.ac.uk/iPr0gram/slides/2015-2016/Marlow-fighting-spam.pdf
そしてSigma の Software Engineering Manager の公募を最近LinkedInでかけていた
職位はManagerだし応募要件にはHaskellスキル必須とは記載していないようなので
Haskellが実用的に使われているっていう傍証にはならないけどプロジェクトは生きてる様子
またその後別の各技術にとってかわられたという情報もなさげ >>898
haskellやってる奴が評価されるのはその手の最適化できることを見込まれてるからだぞ。 Haskellを始めたばかりの者です
do構文は多用しても良いのですか?
手続き型を書いているような気分になります
関数型言語は初めてなので不安です >>918
いいよ。モナドは手続きを実現するのに役立つ抽象だよ。
でもアプリカティブで用が足りるならアプリカティブを使うべき。
IO モナドを do で合成するシーンが多いならリファクタリングの余地があるかも。
Control.Monad や Control.Applicative のユーティリティが利用できないか検討してみて =>= 2020年の抱負 =>=
・珠玉本を再開したい。少なくとも二度目の四天王登場回までは行きたい
・Haskell でごはん食べる >>920
海外にはRemote OKなところあるよ
A List of companies that use Haskell
https://github.com/erkmos/haskell-companies OSS として良さげなツールを作って
Github Sponcers で支援を受ける
って方針を考えてる。どうかな >>925
名古屋の時計販売店BIGMOONさん
https://www.e-bigmoon.com
https://haskell.e-bigmoon.com ってお役立ちHaskell 情報がありがたいサイトやん。
中の人、時計屋さんだったのか… Haskellは妙にテクニカルな部分が多い気がする
2変数関数fと1変数関数gを合成するときに
g . f
ではだめで
g .: f where (.:) = (.) (.) (.)
って書くのとか良く思いつくなって感じ >>928
それは、ポイントフリーで書いているからテクニカルに見えるたけで、
引数を明記すればビギナーにも理解できる式になるぞ。
やってみれば分かる。
他のもそうだ。
例えばライブラリの作者がポイントフリーで書いているのは、
その方がベテランの作者やコミュニティーにとって読みやすいからだ。
彼らもビギナーを相手に解説する際は、
自分達には多少洗練されていない様に見えても、
ビギナーにとっての読みやすさを優先する。
日本語の文章における「漢字」と「かな」の関係のようなものだ。 >>929
(((.) (.) (.)) g f) a b
をパパっと
g (f a b)
に式変形できる自信が無い g . f がだめな理由は型なので
fun<A, B> g;
fun<C, fun<D, A> > f;
このような型を宣言できる任意の言語に同じ問題がある
また、他の言語で問題が解決されたらHaskellでも解決できる >>931
g :: b -> c
f :: a1 -> a2 -> b
に対して
(.) :: (b -> c) -> (a -> b) -> a -> c
の a を a1 -> a2 と解釈してくれれば話が速いんだけどね
a1 -> a2 -> b が実際には a1 -> (a2 -> b) で要は(->)が右結合だから駄目なのよね >>930
すまん、そういう話ではない。
「妙にテクニカルな部分が多い」と言うのは、
君の感じたhaskellの不満点や欠点なんだと俺は捉えたが、違うか?
2変数関数と1変数関数とを合成する関数(.:)の「型がまず先」にあって、
(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> -> d)
これを実装するのに
(.:) = (.) (.) (.)
と書く者もいて、君に妙にテクニカルだと感じさせるのかもしれないが、
(.:) g f = \a b -> g (f a b)
こう書けば、ビギナーにも容易に意味が読みとれる。
テクニカルでは全然ないだろう。
君が妙にテクニカルだと感じる大部分はhaskellの生来のものではなく、
単にビギナーに読めるようにも書けるコードをたまたまテクニカルに書いただけだ。
身の丈や好みに合った書き方をすれば不満に感じることはないだろう、と言いたかった。 >>933
Haskellに不満を持ってるとかではなくて単に凝った式に良く出会うというだけの話よ
そして凝った式を同値変形で分かりやすい式に変形するのが難しいことも多いと思う
個人的にはどう実装するかよりもどう同一視するかの方に興味がある >>935
そうだったのか、俺の完全な勘違いだった。
長文でレスの流れぶった切ってすまなかった。 >>936
謝ることは無いよ
自分も言葉足らずだったし
興味深い話が聞けて良かった 凝った式を書ける俺ってイケてる!っていう中二病の文化なんでしょ リストの1要素を書き換える関数が用意されてないのは、それが非推奨だからなの?
配列みたいな気分では使えないのかな IOが非推奨ではないから
まるでIOが非推奨であるかのような関数が用意されていない事に違和感はない 書き換え・・・?
Haskellに書き換えという概念がそもそもあったっけ? 書き換えができるデータ型は定義できる
それを定義したモジュールにはその概念がある
そのモジュールと概念がHaskellの中にあるのか外にあるのかは知らん すみません質問なんですが、
f [5,4,8,7] == [5,(5+4),(5+4+8),(5+4+8+7)]
みたいな関数を作りたくて
g :: [Int] -> ([Int],[Int])
g (ys) = (ys,[1..length(ys)])
h:: ([Int],[Int]) -> [Int]
h (xs, []) = []
h (xs,y:ys) = sum (take y xs) : h(xs,ys)
f = h.g
と書いたんですけど、これって関数合成以外の方法で書けますか?
出来れば一つの関数で定義したいんですが、行き詰ってます(汗 コレはダメ?
sumlist [] = []
sumlist (x:xs) = x:(map (+x) $ sumlist xs )
main = do
print $ sumlist [5,4,8,7]
print $ take 10 $ [1..]
-----
[5,9,17,24]
[1,2,3,4,5,6,7,8,9,10] 間違った
sumlist [] =[]
sumlist (x:xs) = x:(map (+x) $ sumlist xs )
main = do
print $ sumlist [5,4,8,7]
print $ take 10 $ sumlist [1..]
----
[5,9,17,24]
[1,3,6,10,15,21,28,36,45,55 Data.List.scanl1 (+) [5, 4, 8, 7] == [5, 9, 17, 24] 944です。返信が遅れてしまってすみません。
>>945.947-948 さん早速の返答ありがとうございました。 4.7. GHCi commands
https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#ghci-commands
Prelude>:?
Prelude>:browse Data.List
scanl :: (b -> a -> b) -> b -> [a] -> [b]
GHC.List.scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl1 :: (a -> a -> a) -> [a] -> [a]
scanr :: (a -> b -> b) -> b -> [a] -> [b]
scanr1 :: (a -> a -> a) -> [a] -> [a] Haskellの事を知れば知る程(圏論含む)、数学ってプログラミング言語だなと思う。
コンピュータが登場する遥か以前からあるプログラミング言語。
そうなると数学者はある種のプログラマーと言える。
ただ、数学はコンピュータに計算させるのではなく、自分で計算するから再帰みたいなループ構造は面倒臭い。
そこでループ構造を排除するアルゴリズム(法則や公式)を考え出して来たと考えられる節があって…。
そう考えると、コンピュータの登場で人間の効率的なアルゴリズムを考える能力が退化したかも知れん。
とか、考えてみたり。 ΣとかΠは実質ループだが数学ではループしないで計算出来る 無理数や積分はほとんど計算してない
C++のtemplate実体化してないメタプログラミングと同じ 普段のプログラミングでカリーハワード対応が出てくる場面ってどういうとき?
型レベルで凝ったことをするとプログラムを証明として書くことがあると思うんだけど、
その証明として書いたプログラムは実行するとどうなるの?
この辺少し勉強したいんだが書いたことも見たこともなくてさっぱり想像つかない C++のデザインパターンとHaskellの代数的データ型の同型対応 数式の末尾再帰なfib関数を見た時、手続き型言語で書く副作用バリバリのfib関数との共通点が見えた。
(過去どこかに本の中身の画像落としたんだが、まだあるかは知らん)
そこで一つの仮説が浮かんだ。
入出力を伴わない関数であれば、副作用のある関数でも正しく動く関数は数式と相互に変換出来るのでは?
(入出力も含めるなら、相互にHaskellと変換出来る?逆に、バグがあるなら相互変換は無理?)
数学専門じゃないから、証明とか出来ないけども。 何か知りたいことがあるのか?
需要がないところを努力するのは意味不明だし、努力して欲しいと言うのも意味不明 数学だけだなく国語力もないのな
努力といわれてバカにされてることに気付かない 数学、糞苦手な俺
プログラムで表現出来る数学分野ってごく一部だと思ってたけどそうでもないんか?
概念操作のプロセスと計算とじゃ大きな開きがあると思うんだが
それを鬼計算量で埋められるんかね オペレーションズリサーチって言った分野は数学必須だろうね
ベイズ統計とか当たり前のように使われているし
カルマンフィルタもそう
確率統計/多変量解析はコンピュータやる人間ならそれなりに必須だと思うし
現実世界に役立っている
ここでよく題材として挙がるのは圏論だけど これは俺も必要性はあんま感じない >>959
手続き型言語でのwhileなどの繰り返しの一回に対し、そこで用いられている変数の値の変化を、末尾再帰関数の引数の変化に置き換えれば、きれいな1重whileは、きれいな末尾再帰関数に置き換わると主張しているんだよね。 フリーハンドで描いた線と定規で描いた線を比較するようなもの
実質的な意味は同じ
強いて言うならマナーの良さが違うだけ 静的単一代入形式に変換して、
φ関数の出てくるところを別関数の呼び出しに変換すれば、
副作用のない状態には持ち込めるかな >>966
> ここでよく題材として挙がるのは圏論だけど これは俺も必要性はあんま感じない
プログラムを書く立場ならば圏論なんて知る必要は全くないよ
そもそも仮に圏論を知らないと良いプログラムが書けないプログラミング言語があったとしたら
そんなプログラミング言語は使い物にならない
Haskellerなど一部のプログラマの間での昨今の圏論ブームは少なくとも私には単なる一種のファッションの流行にしか見えないし余り意義を認めない
他人の趣味にケチをつける気はないので、やりたければどうぞ御自由に、としか言いようがない
圏論を知る必要があるとすればプログラムを書く人間ではなくて新しいプログラミング言語の設計をする人間(の一部)だ
ただ一つだけ圏論の勉強を擁護しておくと、規模の大きなソフトウェアをメンテナンスしやすい見通しのよい構造を持つように設計する上では
抽象化と一般化という思考能力、ある事柄や概念と他のどの事柄とが対応するのかを適切に理解し判断する能力は非常に重要だ
そして数学において圏論の最も重要な効用は正にそういう一般化や抽象化といった思考法を書き表すための言葉としてだ
数学である分野での成果(例えば幾つかの定理や定義)を全く別の分野へと転用するといった数学の発展させ方が可能になったのは
正に20世紀中盤に圏論という言葉が生まれたからこそのお蔭だ
だからプログラマが圏論そのものを勉強する必要性は乏しいと思うが、圏論を勉強して理解できる能力と大規模のソフトウェアを良い構造で設計できる能力とは
間違いなく共通した部分があり、正の相関があるのは確実だと個人的には考えている
そういう意味では圏論の勉強は大規模ソフトウェアの設計に向く設計者か否かのフィルタリングに使えるかも知れないね >>970
>そもそも仮に圏論を知らないと良いプログラムが書けないプログラミング言語があったとしたら
CPL(Categorical Programming Language)
まずは Wikipedia を参照汁 一つ言えるのは圏論ってなんか語りたくなっちゃうものなんだということ。
プログラムにおいては全く意味はない。
計算機の動きを抽象化する道具としてそんな筋のいいものではない。
数論でも勉強するなら意味はあるだろうが。 圏論はどちらかといえばポイントフリー
λとか∀とか∃とかパターンマッチとかで変数を束縛する言語
に違和感があれば圏論を語りたくなる >>970
大規模ソフトウェアのメンテにおいて、
圏論を知らないとこのように失敗するが、
知っているとこのように成功する、
という具体例を挙げられますか?
または、具体例を挙げて説明している本やブログ、
カンファレンスなどを紹介できますか? >>978
それは分かっています。
>>970 が圏論による成功例を知っているのなら教えてほしかったのです。
一件も挙げられず、ただ大規模ソフトウェアには大事だと言っているだけでしたら、
とても残念です。 お前が圏論理解してかつ大規模ソフトウェア開発で失敗したら反証になるじゃん
がんばれ >>980
この件に関して反証しても、大した意味はないと思います。
具体的な成功例を一つでも知ることの方が遥かに役立つのではないでしょうか。 圏論だのモナドだの相変わらずだなあ
もっと楽しい話をしようぜ
コモナドとかProfunctor Opticsとかサ 横からだが
個人的に考えてる、と断ってるじゃん
単なる個人の感想
お前はそこに証拠を求めてる
何がしたいの? >>983
個人的でもそう考える根拠が何かあると思います。
何かの記事でそう語っているのを見たとか、
自分が携わったプロジェクトで実感したとか。
記事なら出典を知りたいですし、
実感したのならもう少し具体的な話を聞きたいです。
と言うのも、今までもここで圏論を語る人はたくさんいましたが、
私の知る限り誰一人として役立った例を具体的に語った人はいませんでした。
>>970 は久しぶりに長文で熱く語っておられるので、
もしや具体例を挙げられるのではと思い聞いてみました。 >>971
そりゃ学位論文レベルの言語ならあるさ
そもそもそのCPLとCSL(Categorical Specification Language)とを定義した萩野達也氏のエジンバラ大学に提出した件の学位論文は私も読んだ
そして理論的には大変に興味深い研究だと思ったよ
だが私が前の投稿で書いた「使い物にならない」の定義、つまり肯定形の「使い物になる」はソフトウェア工学的な意味で実用になるという意味だ
つまりは「多数のプログラマによって実用プロジェクトで使える言語」という意味だ、より具体的な基準が必要だと言うのならば
「最低でも100万行のソフトウェア開発をそのプログラミング言語で行える」という意味だ
君が私の主張である「使い物にならない」を否定したければ、100万行とは言わぬまでもせめて10万行のソフトウェアを
複数人で開発するのにCPLだけでやってみてくれ、もちろん必要なCPLのライブラリ類は自分達で開発してね 簡単な判別法がある
デバイスドライバーが書けない言語は使い物にならない >>977
だから能力として近いと言っているだけだよ
圏論という理論を勉強して理解できる能力と、大規模ソフトウェアを良い構造で設計する能力とはね
私がそう考えている理由は、どちらも抽象化や一般化といった思考の能力が重要だからだ
圏論を知らなければ良い設計が出来ないと言っている訳では決してない
970の最後の3行(空行はカウントしない)の意味するところは
勉強すれば圏論を理解できるようになる人は(抽象化や一般化の思考能力が高いので圏論を勉強していなくても)良い設計ができるだろう、という予想だ >>987
> デバイスドライバーが書けない言語は使い物にならない
それは又一つ別の定義だね
私個人としてはアプリケーションしか書けないプログラミング言語でも「使い物になる」ことを認めるけれども
そういう定義をするソフトウェア技術者の立場はそれとして否定する気はない 人間の社会の役に立つ勢力の定義が存在するのか?
まずは存在を疑うのが無駄な努力をしない秘訣 圏論が実用言語に向いてないのと同様に、989は5chに向いてない javascriptでデバイスドライバは書けないわな
圏論とやらが必要な分野で使えばいいだけの話 >>990
未知のウィルスに対する検疫等の防衛が出来るのも人間に役立つ能力
いまの役人の対応観てたらあほばっかりだと思うだろ まだ定義してないのにフライングできる奴は
定義が存在しないパターンを知ってるからそれができる HListのインサートとかソートとかのやり方の実装が乗ってるホームページ教えて
作ろうとしても難しくてできないから このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 377日 11時間 23分 12秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。