関数型プログラミング言語Haskell Part13
1 :
デフォルトの名無しさん :
2010/10/10(日) 19:34:34
__ , ‐' ´ ``‐、 / ̄:三} . /,. -─‐- 、. ヽ / ,.=j _,.:_'______ヽ、 .! ./ _,ノ `‐、{ へ '゙⌒ `!~ヽ. ! /{. / `! し゚ ( ゚j `v‐冫 , '::::::::ヽ、/ そんなことよりDelphiしようぜ! . {.l '⌒ ゙ 6',! / :::::::::::::::/ __ . 〈 < ´ ̄,フ .ノー'_ , ‐'´::::::::::::::;/ (_ノ)‐-、 . ヽ.、 ` ‐", ‐´‐:ラ ':::::::::::::::: ;∠. ヽ_} ゙ヽ ,.r` "´ /:::::::::::::::::::ィ´ `ゝ !、 / / / :::::::::::::::: ; '´ /´\ / r'\ . i ! ::::::::::::::/ 墨 | .!::::::::/ヽ、.._!ヽ. ヽ、 { {:::::::::::;:イ / ‖i:::::::/:::::::::::::/ \ . ヽ ヽ,.ァ‐'´ /ヽ 二 ,/`ヽ、::::::::: /
__ , ‐' ´ ``‐、 / ̄:三} . /,. -─‐- 、. ヽ / ,.=j _,.:_'______ヽ、 .! ./ _,ノ `‐、{ へ '゙⌒ `!~ヽ. ! /{. / `! し゚ ( ゚j `v‐冫 , '::::::::ヽ、/ そんなことよりC#しようぜ! . {.l '⌒ ゙ 6',! / :::::::::::::::/ __ . 〈 < ´ ̄,フ .ノー'_ , ‐'´::::::::::::::;/ (_ノ)‐-、 . ヽ.、 ` ‐", ‐´‐:ラ ':::::::::::::::: ;∠. ヽ_} ゙ヽ ,.r` "´ /:::::::::::::::::::ィ´ `ゝ !、 / / / :::::::::::::::: ; '´ /´\ / r'\ . i ! ::::::::::::::/ 墨 | .!::::::::/ヽ、.._!ヽ. ヽ、 { {:::::::::::;:イ / ‖i:::::::/:::::::::::::/ \ . ヽ ヽ,.ァ‐'´ /ヽ 二 ,/`ヽ、::::::::: /
fmapの代わりに<$>を覚えたよ!(o^∀^o)
<$> くらいはいいけど、算術以外の中置演算子はほどほどにな 調子こくと自分でも何やってるのか分かんなくなるから 俺は、最近は関数を中置で使うことが多くなってる こっちも、調子こくとエディタの編集画面かうざくなるが a `fmap` b
むしろshe(プリプロセッサ)を使って f <$> a <*> bを(| f a b |)と書くとか ただしエラーメッセージが解読不能になる諸刃の刃
>>11 そんなのあるんだ。
>>9 じゃないけど、勉強になった。
サンクス。
公式のLLVMの切れたリンク、なんなの?
なんなの、って、メンテ忘れじゃない?
15 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/16(土) 16:44:43
ほんとこのクソスレのびねえな 終了〜
vip de yaruo.
Pearls of Functional Algorithm Designやっと届いたぜ。wktkしながら頁をめくるか
>>17 俺もちょっと前から少しずつ読んでる
15ページ目でいきなり躓いてるがな
FRP の Arrow による実装に興味がある者には下記の論文を勧める Plugging a Space Leak with an Arrow Arrow 以前の実装で起きてたスペースリークを Arrow で解決した話が詳細に書かれている
20 :
まつもとひろゆき :2010/10/18(月) 17:07:35
こんなゴミスレいらん。
25 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/18(月) 23:56:01
20~24はHaskell板にふさわしくない書き込みですね 20〜24だけをみると まるでHaskell板の面影すらありません そう思いますよね???
itパスポートは どうなったよ??
27 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/19(火) 09:33:28
JPA公認企業の20台後半〜50台くらいのやつが消滅したらPerlerの大半が消える
28 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/19(火) 09:38:45
Perlerってモダンの書き方しってるやつな くそみてええなのは含まれません!
クソコテにかまうな
まさに糞コテだよな。 有益な情報を一切ださない奴。
みんな喧嘩は辞めて!><
33 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/20(水) 11:31:10
FPS勝負しないか? haskellじゃねーぞ プログラマと1回 FPSをやってみたいんだけど お前らができるFPSをいってくれ 俺はそれをダウンロードしてスタンバイするので
言っておくが俺はチートするぜ
35 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/20(水) 12:11:30
チーとでもなんでもこい 早くFPSのゲーム名いえよ
DOOM
37 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/20(水) 12:24:26
doom知ってんぞ体験版? はやくURLはれ
馬鹿はテンション高いな
39 :
デフォルトの名無しさん :2010/10/20(水) 18:59:53
FPSあげ
FPSあげ あげ
むしろFRP希望。
FRPを使ったゲームを誰が最速で書けるか勝負しようぜ!
44 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/20(水) 23:00:21
>>43 俺の偽だろ!!!
ガッチムッチの思い切り!ガッチムチ羽ばたいて!飛んで飛んでアソコへ!レディゴーレディゴー!レディゴー!(ガチガチ! oh〜ガチムチー!!!
ところで、Perl忍者は Haskell は使えるのか? 使えるのなら、小粒でいいから何かテクニックでも紹介していけ 使えないのなら、邪魔だから騒がしくするな
ちょっと前にHaskell勉強しはじめた者ですが、 小難しいモナドでつまづいてます。 皆さん何を勉強してモナドが何者か納得できましたか? とりあえずWadlerの論文みつけたので、 これ読めばなんかつかめるかなとは期待してるんですが、英文だし効率悪い。
おお、さっそくありがとうございます。 おすすめのページじっくり読んでみます。 まずはお礼まで。
>>46 [モナド] を理解することと、
[モナドで副作用を閉じ込める仕組み(IO モナド)] を理解することは別だからね。
[モナド] と [モナドの演算] というのは、有理数と割り算みたいなもの。
[有理数]
1. 整数 x を □/1 でくるめば(x/1)有理数になる(整数を有理数に変換)
2. 有理数どうしならば割り算(÷)という特別な演算ができる
3. 割り算した結果できたものもまた有理数だ
4. 有理数には特別な性質がある(4/8 も 2/4 も既約分数にすれば同じとか、ゼロでは割れないとか)
[モナド]
1. 何でもいいが何か x を return □ でくるめば(return x)モナドになる(何かをモナドに変換)
2. モナドどうしならバインド(>>= や >>)という特別な演算ができる
3. バインドした結果できたものもまたモナドだ
4. モナドには特別な性質がある(モナド則とよばれるルール)
モナドとは本質的に何か探るのではなく、こういうことができるものにモナドと名前が付いてる、
という方向からモナドを理解するやりかたもあるよ。
どちらも 1. と 3. は何も特別なことはなく、各々の特徴は 2. と 4. に現れている。
だから 2. と 4. がどのようなものかを知れば、モナドが見えてくるよ。
50 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/21(木) 08:08:02
本かわせんじゃねえよ作者
51 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/21(木) 08:11:15
本買わせるんじゃねえよ著者
モナドの目的は、本来の目的を情報隠蔽することだと思います。 問題は、隠蔽するやり方が何通りもあったために、かえって偶有的属性が増えてしまった ということだと思います。
53 :
49 :2010/10/21(木) 09:09:35
>>49 すまん、[モナド] の 2. は違うな
バインドはモナドどうしの演算じゃなかった
[モナド] と [そのモナドで包んでるものに対する関数] との演算だったよ
あと、[有理数] の 1. は別に整数でなくてもいい
複素数でもその他でもいいが、整数が一番簡単だったから
>>52 >モナドの目的は、本来の目的を情報隠蔽することだと思います。
どういうこと?
たとえば、ある代数データ型をある目的で使いたいが、その目的を隠したい、
そういう時にその代数データ型をモナドにすることを考えてみるといい、
ということですか?
>>52 はつまらない冗談か、もしくは気が狂っているので無視していいよ
確かに、本質を見るためには、つまらないものを隠せばよいと思います。 しかし、つまらないという基準はただの主観だと思います。
この世は主観で出来ているのですよ。 あなたはこの世界を五感と知性によって認識しているでしょう。
58 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/21(木) 23:44:59
お笑いブームの影響で おもしろいの基準あがってるからしょうがねえんだよかす
>49 オブジェクト(≒集合の元)を「モナド」と呼んでる段階で眉に唾をつけたくなる.
60 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/21(木) 23:49:01
>>57 てめえ
うちはイタチの真似してんだろこら
「人は己の知識や認識に頼り縛られ生きている…それを現実と呼んでな。しかし現実とはあいまいなものだ。それは幻かもしれない
お前もNARUTO好きか?
>>60 仏教思想で答えただけなんだがな・・・
仏教では、世界とは八識(五感+意識+末那識+阿羅耶識)で物事を認識することによる主観の産物だっていうのが定説。
62 :
49 :2010/10/22(金) 07:32:55
>>59 俺自身も書いた後でこの捉え方はどうかとちょっと疑問だった。
(いろいろ突っ込みどころはあるだろうし)
が、少なくともオブジェクト(≒集合の元)を「モナド」と呼んだつもりはないのだが。
[モナド] の 3. のところがマズったか。
小学校や中学校、高校で「割り算とは何ものか?」という本質は学ばず、
「割り算は**という演算だよ」とだけ教えられ、さっさと学習を進めたはず。
微分、積分、内積なども同じだと思う。
ちょっと前に Haskell 勉強しはじめた者も Haskell に関しては同じ立場だから、
「モナドは**という演算ができて、##という性質があるよ」
の**と##をまず調べたらどうかと言いたかった。
それはモナドの理解のほんの一部だけだけど、
それだけでも Haskell の学習を進めるのには十分だから。
63 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/22(金) 07:38:55
仏教
>62 「1を return でくるめば(return 1)モナドになる」 「(Just x) と (Left y) (モナド同士)に特別な演算ができる」 って変でしょ? (return 1)の属する型(IO Int なり Maybe Int なり)と演算 >>=, >>, return の組がモナド. あなたの書き方だといつでもモナドの元同士に対する演算が定義されていると読めて, データを型で区別してプログラムの質を高める,という考え方と真っ向から対立し 読者に混乱を引き起こす.
仏教≒マトリックス これならここの住人にも理解できるんじゃないか。
モナドの一つの側面は 一度その型で始めたら途中変更は利きませんからね って事ですかね
ですかね と問われたら違うというほかない
68 :
49 :2010/10/22(金) 12:39:49
>>64 演算はモナドどうしではなかったと
>>53 で訂正したぞ
(>>=、>> の右辺はモナドじゃないから)
>>66 できるよ
[String] から [Int] に変更できるでしょ
そうですか、違うんですか(´・ω・`)
初心者が具体例なしに理屈だけ聞いて分からないから困ってんのに 変な理屈だけ増やしてどうすんだろな モナドを使わずに書いた場合と比べてみれば 少しはありがたみが分かる
>>70 >初心者が具体例なしに理屈だけ聞いて分からないから困ってんのに
そんなこと一言も聞いてないが
逆に例ばかりで理屈が分からないとも聞いてないけどね
自分が知りたいんだと素直に言ったら?
世界は人の主観の産物なのだから本質は「無」なのだ、というわけ。
いつからこのスレはこんな電波っぽくなったんですか?(´・ω・`)
仏教を電波扱いするな。 お釈迦さんバカにすんあ
猿が増えたから減らします
電波ぽいって主観じゃん
とりあえず主観は悪くないとしても 他人の主観に便乗するやつはゴミ
スレの住人が総取っかえになったみたいだな。
haskellは仏教に似ている
ヘイ! ジョージ! 今日も情事に励んでるかい? HAHAHA
その話題はもう完了してる 今ほっとな話題は仏教だよ
84 :
Perl忍者 ◆M5ZWRnXOj6 :2010/10/22(金) 23:22:49
うけるwwwwwwww 一瞬ここのスレみたら 仏教スレになってた テラワロスwwwww
バイアスがひどいな。政治の道具にされ始めとる。
荒らしに対抗できるのは荒らし Perl忍者!頼んだぞ!
釈迦(=仏陀=目覚めた人)はむしろ幽霊とか超常現象とかオカルトを批判していた側の人間なんだがなw 紀元前500年のインドはオカルト宗教であるバラモン教が力を持っていたが、 そのアンチテーゼとして釈迦の教えをまとめたのが仏教(上座部仏教)だ。 神に祈れば天国に行ける?バカをいうなw 仏陀は弟子にこういった、 小石を池に投げ込んで、浮かんでこい、浮かんでこい、と念じれば小石は浮かんでくるのか? いや、浮かんできはしない。 念仏や祈祷や呪文を唱えたところで何も変わらんのだ。 そのくだらん映画を今すぐ取りやめろ。
今の日本で普及しているゴミのような仏教は釈迦が死んだ700年後の後世に作られた大乗仏教に由来する。 この大乗仏教というやつは仏陀の教えを経典主義的に極端な形で屁理屈をこね回して作られたオカルト要素たっぷりのゴミ宗教だ。 そう、どんな素晴らしい教えでも凡人にかき回されるとゴミに変貌するわけだ。 Haskellだって、凡人が大量に使うようになると当初の理想なんて失って優柔不断な言語になるに決まっている。 だからperl忍者とかいうザコはどうしてもHaskell触りたいなら博士号取ってからにしろ。
90 :
デフォルトの名無しさん :2010/10/24(日) 19:27:54
シッタルダの考えやHaskellの当初の理想なんってどうでもいいんだよ。 世間が求めているのは便利なものだ。 大乗仏教は人々に支持された。 Haskellは?
F#でも使ってろ、が答えだと思う
もしかして、CommonLispの方ですか。
>>90 少なくとも嫌ってる人は少ないだろうな
大半は「好き」「はぁ?何それ」 のどちらかだろ
儲はどこもキモイな〜
具体的なことは何も言えないわけですねわかります
10スレ前ぐらいで虐められた奴がまだ粘着しているって感じやね
97 :
(信は力なり)Perl忍者 ◆M5ZWRnXOj6 :2010/10/25(月) 23:27:04
>>89 最後の行にPerl忍者とかかかれてもきずかないんですが
死ねよハゲ
Arrow がなぜ生まれたのかを知りたい人たちに John Hughes が著わした次の論文を紹介する。 Generalising Monads to Arrow モナドの利点も簡潔にまとめてあるから、 モナドって何の役に立つんだ? という人にも参考になる。
>>98 論文のタイトルが間違ってた。
細かいことだが著者に失礼なので訂正させてほしい。
Generalising Monads to Arrows
IOモナドのような副作用系のモナドは、 1. Stateモナドを一回写経 2. loop :: Monad m => Int -> m a -> m a とか、when :: Monad m => Bool -> m a -> m aのような 『モナドをとってモナドを返す』関数をいろいろ作り、Stateモナド内では何が起きているのかを考える 3. 全部消してStateモナドを記憶を頼りに再実装 ってやればかなり理解できる。 Listモナドは、リスト内包表現をListモナドで表現するのを繰り返していれば、分かってくる。 Maybeモナドはその劣化版。 これらはすべて一本道の逐次計算あるいは逐次実行、すなわちモナドが抽象化しているものの具体例になるんだけど、 そこまで行く前に、StateモナドとListモナドを別々に理解して、いつでもモナドのインスタンスとして再実装できるようになるほうが、 数学者でなければ結局は早いと思う。 いずれ、Listモナドは量子ピタゴラススイッチなのだと理解できる日が来よう。
>>100 >Maybeモナドはその劣化版
何となくだけど、ちょっとだけ引っかかる。
Monad クラスのインスタンスは全て等しく優劣無くモナドなんじゃないの?
何の視点で優劣を比べた結果 Maybeモナド が List モナドに劣ると考えたの?
議論の本質ではないが、 Monad クラスのインスタンスがモナドとは限らないことには注意されたい。 もちろん、処理系が提供しているものに関しては整合性がとれるように設計されているはずだが。
>>101 僕の誤解でなければ、[a]の値をaを0個か1個持つものだけに制限すると、
理論的(代数的)にはMaybe aとまったく同じもので、
それはMonadoクラスとしての働きもまったく同じはず。
Monadoとか書いちゃった。oが多い。 サーセン。
Maybeをモナドとして使う時はリストで完全に代用できるってことだな Data.Maybe.maybeToListを使うと、Maybeの値をリストに変換でき、さらにこの変換がMonadインスタンスと整合する 整合するというのは以下の二つの法則が成り立つこと(なんか圏論の臭いがする) maybeToList (return x) = return x maybeToList (x >>= f) = maybeToList x >>= maybeToList . f
>>103 なるほど、数学的には リストモナドは Maybe モナドを含んでいること、
その観点で Maybe モナドはリストモナドの劣化版だと言ったのは理解した
同意する
ただ、ちょっと確認しておきたい
数学的には同じでも、実際問題としてプログラムソースの中で Maybe a を使ってた所を全て
劣化版を完全版にしようとして要素が0個か1個の [a] で置き換えたらまずいよな?
ソースを保守しにくくなるよな?
そういう観点では、リストと Maybe は優劣を比べるものではなく、
むしろ全く別の役割のものだよな?
なるほど、[]=Nothing/[a]=Justか 横レスだけど、MaybeをListに置き換えると、 要素は0個か1個、という制約が抜け落ちてしまうから 置き換えることは出来るにしても、設計的には酷くなるからやめた方がいい 誤解に対しては、「劣化版」じゃなくて「特殊化版」って語を使えば良かっただけの話じゃないかな
そのままでも使えるものに余計な装飾を施すことを劣化と言うなら、 newtypeなんか劣化の極みになるんじゃねいの
>>107 「モナドとして、returnと(>>=)で操作する限りにおいては」リストを不自由にしたものに過ぎないと言えるけど、
値を取り出すことやその他の操作を考えれば劣化じゃないし、もちろんコーディング上の役割は違う
「劣化版」という言い方がよくありませんでした。ごめんなさい。
>>100 で言いたかったことは…
リストモナドの働きを理解すればその特殊化版であるMaybeモナドの働きも理解できるよ、
それと、IOモナドはStateモナドで理解できるから(Rreaderモナドなども)、
ひとまずStateモナドとMaybeモナドを理解すれば十分に視野が開けるよ、
ということです。
もちろん、何かを理解するための試行錯誤の上ではなく、
実用のコード上で、一般にMaybe aをList aに置き換えてしまうのは危険です。
ここまでの議論を纏めます ・Maybeモナドは、Listモナドの要素数を0か1に制限した 特殊な例であるという見方ができる ・Monadクラスのインスタンスがモナドであるとは限らない ・Perl忍者は電波である
・Maybeは、Listに置き換えると危険である ・「コンパイルできたら安全」とは限らない ここからの議論を期待します
Haskellはオブジェクト指向ができますか?
専用のサポートはないけどできる カプセル化と多態はそのための機能がある。実装の継承の仕組みはない メッセージ渡しはちょっと無理があるかも
data Acceptor a b c = Acceptor (Visitor a b c -> c) data Visitor a b c = Visitor (a -> c) (b -> c) accept (Acceptor accept) visitor = accept visitor leftAcceptor x = Acceptor accept where accept (Visitor visitLeft visitRight) = visitLeft x rightAcceptor x = Acceptor accept where accept (Visitor visitLeft visitRight) = visitRight x
Haskellでオブジェクト指向でプログラミングしないでください。
それは何故ですか?(´・ω・`)
QuickCheck の orderedList 関数は、説明には 与えられた長さの順序リスト生成器を生成するようなことが書かれていますが、 vector 関数のような引数は無いですよね。 どうやって長さを指定するのでしょうか。 resize 関数を作用させるしかないですか?
オブジェクト指向は目的ではなく手段だから
>>119 orderedListの定義はsort `fmap` arbitraryだからのぅ
fmap sort . vectorで代用すりゃいいんとちゃうか?
関数型言語とオブジェクト志向って直交する概念だよね?
>>121 なんか解説と違ってていまいち納得いかないが、
実用上はそれで問題ないような気がしてきた
ありがと
>>122 同じ名前で異なるメソッドが呼ばれると嫌がられる気がする
高階関数は良いが、関数のタプルとか関数のリストとかはだめっぽい
なにその偏見
>>124 ちょっとまった。 Haskell でもオーバーロードがあるだろ。
>>126 あるね
オーバーロードも嫌がられる場合がある
例えば、MaybeなのかListなのかはっきりしろ、みたいな
諸君、ようやく議論を始めたようだね
型変数を伴うデータ型がインスタンスとなるような型クラスにおいて、 その型変数もシグネチャに取り入れた関数を定義したいです。 次のようなイメージの型クラスです。 class P (p a) where ext :: p a -> a で、次のようなデータ型を用意し data Test a = T (a, a) 次のようにインスタンスを宣言したい。 instance (Num a) => P (Test a) where ext (T (x, y)) = x + y しかしこれでは型クラスの定義の class P (p a) where の所でエラーが出ます。 Type found where type variable expected 本来 class P のすぐ後には型変数が来るべきですが (p a) と書かれていて、 型変数が書かれていないといった旨のエラーだと思います。 このようーな型クラスは作れるのでしょうか。 作れるのなら、どのような方法で作れるでしょうか。
>>129 これでは駄目?
class Monad m where
return :: a -> m a
131 :
130 :2010/11/01(月) 20:10:07
ごめん勘違い。Haskell2010の範囲では無理 GHC拡張を使っていいなら {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} class P p a where ext :: p a -> a data Test a = T (a, a) instance (Num a) => P Test a where ext (T (x, y)) = x + y
>>131 > GHC拡張を使っていいなら
全く問題ないです。
ありがとうございます。
助かりました。
「オートマトンの範囲では無理」「CFGの範囲では無理」なら分かるんだが 型システムの表現力を見積もる基準とかってある?
134 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/04(木) 17:10:49
Haskellで何作ってんの? どうせゴミだろ
>>133 とりあえず、Agdaのような「値」を型構築子の引数にとれるものと、
それができないHaskellのようなものの間には、原理的な違いがあると思う。
依存型か
計算とリフティングはどうなる。
いまさらだけど、RWHをはじめのページから読み出しました。 10章の246ページで挫折しました。 コードが何やってるか分かりません。
>>139 なんだ、クイックソートか・・・
よく読めとしか言いようがない。
RWHは原著しか読んだこと無い どんなコード?最初の数行だけでもいいから貼ってくれ あと節の名前(ボイラープレートをなんちゃらとか、グレイスケールファイルとかそういうタイトル)
直前のコードまで理解できただけに、↓が何やろうとしてるのか分かりません。 newtype Parse a= { runParse :: ParseState -> Either String (a, ParseState) } identify :: a -> Parse a identify a Parse (\s -> Right (a, s))
パーサーモナドの定義を作ろうとしているやつか newtype宣言の説明は省略するけど newtype Parse aのaはそのパーサが成功したときaという型のデータを返すという事 ParseStateはパースしたいデータ、入力だ でパースはいつも成功するとは限らない、そして失敗したときにそのエラーの情報を持っておきたい なのでEitherがくるわけだ、そしてこの場合そのエラー情報はStringに決めうちしておくわけだな でパースが成功したときは読み取るのに成功したデータと、入力データのうちそのパース時に使われなかった分を返すと でそれがEitherの第二引数の型(a,ParseState)になるわけだ で次にidentity 一言で言っちゃうとどんな時でもある値を返すパーサの定義だな 試しにrunParse (identity 1) undefinedを展開すると identityの定義より runParse (Parse (\s -> Right (1,s)) undefined runParseアクセッサの定義より (\s -> Right (1,s) undefined 関数適用より Right (1,undefined) さてこの説明で分からなかったことに対する質問をどうぞ
なかなかわかりやすい
145 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/07(日) 11:43:47
無駄に時間費やしてるゴミ
なんだよ、Perlから抜忍したくなったか?
145 ワロタ、消えたかと思ったのに
148 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/07(日) 18:50:16
149 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/07(日) 18:53:49
ギャグが少ないからまともだろNARUTO
RWHの361ページの上段の説明なんですけど、RandomGenとStdGenの関係について書いてあるみたいなんですけど、ここの日本語が分かりません だれか解説お願いします。
たしかに言語明瞭意味不明な日本語ですが、 StdGenのインタフェースはRandomGenクラスのメソッドで、もしInt乱数に特化したければその定義は変えられるし、本物の乱数装置が手元にあるのなら、それを発生源として本物の乱数を発生させる実装も可能だよ。 ということでは。
関数適用の $ って、$ じゃない普通の関数適用で後ろに括弧つけるのと同じ? 括弧はぶいて見やすくしてるだけという認識でおけ?
そうだよ 細かいことを言うと、 ・後ろだけじゃなくて前にも括弧をつける: (f . g $ x)は((f . g) x)の意 ・($)は特別な構文じゃなくてPreludeで定義された演算子(右結合、強度1)
強度1じゃなくて0だった
getStdRandom の引数が 関数 StdGen->(数値, StdGen)で、 randomR (数値, 数値) の結果が RandomGen->(数値, RandomGen) で、 StdGenがRandomGen のインスタンスだから問題ない、と StdGen以外でもRandomGenのインスタンスを用意すればいい、と twoBadRandomsの中に random が説明もなく出てきたんですけど、これは何でしょうか?
>>156 関数や型、型クラスなどが説明もなく出てきた時は、
まずは標準ライブラリのドキュメントを調べてみてください。
ドキュメントの Index を使えば楽に調べられます。
random 関数は Random 型クラスが定義している関数のひとつです。
randomR 関数もおなじ型クラスが定義している関数のひとつですが、
それとは違い random 関数は乱数の範囲を明示せず、
デフォルトの範囲が使われます。
>>158 やっぱり、GHCとドキュメントをインストールして使いながら読まないとダメか…
>>159 使わないで 360 ページまで理解できたのなら凄いですね
162 :
Perl忍者 ◆V8M/4amdko :2010/11/10(水) 17:13:35
ここみてると毎日無駄な事やっててかわいそうに思えてくる なーむーん
そのレスよりは有意義だと思うぞ
164 :
デフォルトの名無しさん :2010/11/10(水) 22:27:28
Perl忍者こそ無能の固まり
165 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/10(水) 22:35:18
ここのスレのやつらはある意味親切だから毎日チェックしてんだよ
どう考えても無駄なことに没頭する これこそが贅沢 これこそがステータス 役に立つことしかやる余裕がない人はPerlでメモ帳でも作ってろ
167 :
デフォルトの名無しさん :2010/11/11(木) 11:57:45
Perl忍者こそ無能の極み
まぁ、少なくとも就職活動には役に立たないね。 何しろ人事担当も経営者も関数型言語の将来性なんて一つも理解していないのだからw
どこの底辺企業だよ
>>169 むしろ底辺の一部のベンチャーほど理解してると思うなぁ。
研究開発部門ならともかく、ついこないだまで日本語の入出力すらまともにできなかった言語を欲する企業があるとは思えん。
>>171 言語が使えるとか使えないという初級レベルの話はしていないと思うなぁw
「幾何学なんかやって儲かるのか」だって? この金やるからどっかに消えろ by ソクラテス
まさかの文字コード さすが馬鹿は発想が貧弱だな
175 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/11(木) 16:54:19
こいつらはラテン系の数式とか書いちゃってw 方程式とかなw 難しくみせて 実は簡単なことやってる低レベルなやつらねw バカだから知的にみらたいでしょ?w そろそろ死んだ方がいいよw
涙ふけよ
くだらないこと書いて、紙を無駄にするなよ? あと、忍者熱烈支持!!!
>>175 お前自分のレスを読み返してみてどんなことを思う?
Perl忍者さんはどのようなお仕事をされているんですか?
そこで、”仕事”が出てくる理由がわからない。 銀行員とか書けば良いんだろうか?或は、議員だとか。 何かこう…
保安官です.
忍者がどのような仕事か知らない人がいるみたいだね
大名に仕えて諜報活動するんだろ?
184 :
デフォルトの名無しさん :2010/11/11(木) 19:32:29
忍者の仕事はオナニー
187 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/11(木) 19:54:12
企業内撮影してアップロードしたら犯罪になる?
188 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/11(木) 20:01:18
189 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/11(木) 20:08:03
残念ながら俺には5名 影武者がいる 全て共有してるからな 俺を潰したければ本物を見つけてみろ
全て共有してるなら、どれも本物だよな
↑亀
反知性主義者は進化論が禁止になってる国に帰れや
195 :
デフォルトの名無しさん :2010/11/11(木) 21:05:44
知性ってなんだよ?
君達、良い加減にし給え。
199 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/12(金) 17:14:08
開発経験はなんですか? 「動画プレイヤーの開発です」 好きな言語はなんですか 「PHPとASです」 なにできる? 「Flash使って動画プレイヤー」 俺「プッ(笑) 「Twitterアプリもつくりましたよ」 みせてください 俺「へー(苦笑
Perl忍者って、Perl以外に何ができるの?
関数の中置記法でカリー化を使うことって、 GHC の拡張なんかでできますか? たとえば次のような感じです。 let f a b c = a * (b + c) in 2 `f 10` 3 予め g = f 10 としておけば 2 `g` 3 でできますが、 上記のように記述できるかなと。 べつに目的はないです。 これが分かりやすいかどうかも考えてません。 単に Haskell で遊んでて、ふと思ったもので。
できません。
諸君、新しい話題は?
ありません。
ないない。
RWHの練習問題の解答例ってどこかにあるのでしょうか? それとも解答例なんか見るまでもなく簡単にできるものなんでしょうか?
URLリストからファイルをダウンロードするスクリプトを書きましたけど、これ、もっと綺麗になりませんでしょうか? -- ここから import GHC.IOBase import System.Cmd wgetCmd :: String wgetCmd = "./wget/wget" -- wget.exe というコマンドがwgetというフォルダの下にある wgetParam :: String -> [String] wgetParam url = ["-r", "-l1", "--no-parent", "-A.jpg", "--header=REFERER:"++url, "-U", "\"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)\"", url, "-e", "robots=off"] testMain = do iStr <- readFile "dList2.txt" -- 行頭にタブ dList2.txt に画像のURLが1行にひとつずつある let ls = lines iStr -- 行頭にタブ wgetMain ls -- 行頭にタブ wgetMain :: [String] -> IO GHC.IOBase.ExitCode wgetMain [] = return GHC.IOBase.ExitSuccess wgetMain (u:us) = do rawSystem wgetCmd $ wgetParam u -- 行頭にタブ wgetMain us -- 行頭にタブ -- ここまで WindowsXPで、ghciの中 で :m System.Cmdの後にtestMainでとりあえずちゃんと動きました 他に、wgetみたいな関数があったら教えてください
>>210 ぱっと見たところ、wgetMain 関数の中は forM_ 関数を使えば
空リストとの場合分けを書かなくて済む。
> 他に、wgetみたいな関数があったら教えてください
haskell の packageDB に http-wget というライブラリがある。
http://hackage.haskell.org/package/http-wget きみと似たようなことをしてる(wget コマンドのラッパー)。
このライブラリを使えば、とりあえず
(_, b) <- wget' "
http:// ・・・hoge.gif" [] []
という記述で b に GIF ファイルの本体が String 型で書き込まれた。
後は標準ライブラリの withBinaryFile 関数を使って、
withBinaryFile "c:\\・・・hoge.gif" WriteMode (\h -> hPutStr h b)
と記述すれば保存されたよ。
ただ、wgwt コマンドにどのようなパラメータを渡しているのかは知らない。
公開されている関数の中には、詳細なパラメータを渡す類のものは無さそうだけど、
デフォルトがどうなってるのかは自分で調べてくれ。
ソースを見れば何やってるのか分かるだろうし。
>>211 あ、ごめん。
wgetMain 関数は空リストだったり成功したら ExitSuccess を「ひとつ」返すのか。
それなら forM_ や forM では意味無いね。
成功や失敗のリストを返すのなら forM を使えばいいけど。
ごめん、
>>211 の前半は無視してくれ。
wget で画像のダウンロード失敗して ExitFailure を受け取ったURLのリストをリストに保存しようと思ったら、URLに画像が存在しなくても 404.html をダウンロードして ExitSuccess を返してきちゃう
>>213 (h, b) <- wget' "
http:// ・・・hoge.gif" [] []
とやって、ヘッダの内容を確認してもダメだった?
それでもダメなら、b の先頭数文字くらいのマジックコードで、
画像ファイルかどうかを判別するとか
curl -I <404.htmlを返すurl>でどんなレスポンスコードがくる? もし404じゃないのが来るようなら自前で判断するコード書く必要がある
216 :
215 :2010/11/14(日) 16:55:50
ごめんスルーで
217 :
デフォルトの名無しさん :2010/11/14(日) 17:57:58
>>210 HTMLテキストファイルから画像のURLを抽出するスクリプト作ってみた
これと
>>210 で画像だけダウソできる(ふたばの二次裏junで確認したけど、多用するとアク禁されると思う)
↓ここから(GetURL.hs)
-- ghci → :load GetURL.hs → getImageURL "HTMLのソースコードが書いてあるテキストファイル" "結果を出力するファイル"
import Text.Regex.Posix
import System.FilePath
import Data.Char (toLower)
urlPat = "s?https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+"
getImageURL :: FilePath -> FilePath -> IO ()
getImageURL inFile outFile = do
{-タブ-} inStr <- readFile inFile
{-タブ-} writeFile outFile $ unlines $ (filter isNotThumb) $ (filter isImageURL) $ ((inStr =~ urlPat) :: [String])
isImageURL :: String -> Bool
isImageURL url =
{-タブ-} case (map toLower $ takeExtension url) of
{-タブ-}{-タブ-} ".jpg" -> True
{-タブ-}{-タブ-} ".jpeg" -> True
{-タブ-}{-タブ-} ".gif" -> True
{-タブ-}{-タブ-} ".png" -> True
{-タブ-}{-タブ-} _ -> False
isNotThumb :: String -> Bool
isNotThumb url = not $ (map toLower url) =~ "thumb" :: Bool
>>217 IMG タグ内の SRC だけを調べた方がよくないか
>>217 相対パス名ガン無視だから、ちゃんと動くのは二次裏だけだと思う
二次裏は、junとかmarとか画像を置いてるサーバを分けてて、全部絶対パス名で書いてるから
www.haskell.orgが見れないのですが、いつからでしょうか。 どなたかご存知ないでしょうか?
>>221 一昨日までは見てたから、それ以降からだろ
良くある、今までも何度もあった
待ってれば数日で見られるようになる
昨日の夜は見られなかったよ
>>222 >>223 ありがとうございます
wxHaskellかGtk2HS試したかったのですが、待つことにします
>>224 どちらも今問題なく hackageDB から落とせるが?
226 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/14(日) 21:48:51
さきりさ っていうやつしね
227 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/14(日) 21:56:00
hageDBみてええだな
228 :
デフォルトの名無しさん :2010/11/15(月) 07:31:16
Perl忍者ぺろぺろ
Haskell の最適化にまつわる話やテクニック、注意などを集めて紹介している 本やサイトはありませんか。 例えば、末尾再帰の形の関数は引数が正格でなければ効率は上がらないとか。 計算量や必要な(メモリ)空間などの測り方とか。 アルゴリズム系の本やブログなんかで少し紹介されてはいますが、 まとまった情報というのがなかなか見当たりません。 日本語・英語どちらでもかまいません。
>>230 すいません、紹介しているという言い方が悪かったです。
カタログ化されてるといいなぁと。
(どこもやってなかったら、自分でやってみようかなとは、ちょっと思ってますが)
紹介していただいた前者のページは初めて知りました。
これは、上のスライドを表示しながら、
ページ下の台詞を講演者が喋っていたというイメージですか。
初めの方をちらっと見ましたが、扱ってる話題が多そうなので、
これからじっくり見てみます。
後者の方は原著(ネット)も和訳も読みましたが、浅い感じでした。
なんというか、少なくともこのトピックに関しては
詳細はウェブで、論文で、他書で、公式ドキュメントでという感じでした。
>>230 忘れてました。
紹介、ありがとうございました。
GHC 7.0.1
234 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/16(火) 17:44:26
イモリ4GBだけどネトゲはサクサクうごきますか?
235 :
デフォルトの名無しさん :2010/11/17(水) 05:46:15
実は俺どうこのベンチを解釈したらいいかよくわかんないんだけど リンク貼っとけば勝手に話を膨らませてくれるだろう まで読んだ
Haskell十分すぎるほど速いじゃん あとLuaが意外と上位なんだね
ほんとだ、LuaがJavaより速い(こともある)のは知らなかった
まぁ、そこそこの努力で十分な速さが出るならいいよな いろんな最適化テクニックを駆使しなければならないとか、 またそのためにソースが見難くなるのなら問題だけど
240 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/17(水) 21:24:00
お前らまだHaskellやってんの 死んだ方が良いよ 親がかわいそう
この忍者の親が可哀想だわ
まさか息子が忍者やってるとは思いもしないだろうなw
244 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/18(木) 22:15:47
いテレパシーがとんできました haskellスレから 誰かいまテレパシーをおくったか? お前らかわいそうだよ haskellやって ゴミ掃除やってるレベルだろ
Luaが速いというか、LuaJITが速いみたい Haskellが今より20%くらい速くなると、ほぼJavaの水準になるね
じゃあ誰が20%速くしてくれんだよ! Ruby高速化したあの少年連れて来い!
247 :
デフォルトの名無しさん :2010/11/19(金) 10:03:03
RWHの次に読むべき英語の書籍ってなんだっけ?
何がしたいの?
万能感を錯覚したいです
それならRWHとか読んでないで然るべきクスリを使うべき
では質問を変えます 最も新しく発売されたHaskellの書籍は何ですか?
>>251 Concurrent Haskell
(ISBN-13: 978-6133152977)
たぶん、これが最新だと思う
内容は知らん
あ〜これだったかなぁ?違ったかなぁ? 前スレの末尾までの時点で最新だった奴だと思うんですけどね
>>253 じゃあこれか
Pearls of Functional Algorithm Design
(ISBN-13: 978-0521513388)
次のような型クラスと関数があるとします。 class Trans t where fromList :: [a] -> t a toList :: t a -> [a] trans :: [a] -> [a] trans = toList . fromList ここで Trans 型クラスのインスタンス T1 と T2 があって、 T1 の trans の結果と T2 の trans の結果が 同じなら True 違うなら False を返す関数を作りたいです。 (QuickCheck で確認したい) しかし、この trans 関数をそのまま使ってそのような関数を作ることは できないのでしょうか(型シグネチャをどこかに明示して)。
>>256 無理
そもそもtransの型が曖昧でコンパイル通らない
>>257 では、
transT1 :: [a] -> [a]
transT1 = t . f
where f = fromList :: [a] -> T1 a
t = toList :: T1 a -> [a]
transT2 :: [a] -> [a]
transT2 = t . f
where f = fromList :: [a] -> T2 a
t = toList :: T2 a -> [a]
などと、T1 T2 それぞれ用の trans 関数を作って、
それらを比較しなければならないのでしょうか。
transT1 と transT2 は T1 や T2 といった型のみが違うだけなのですが、
どうにかしてこの型をパラメータとして指定できる関数は作れないものでしょうか。
>>258 transの型シグネチャにtが入るように無理矢理にでも変形すればいい
やりかたは複数あるけど、例えば、
{-# LANGUAGE KindSignatures, ScopedTypeVariables #-}
data Wrap (t :: * -> *) = Wrap
trans :: forall a t. Trans t => Wrap t -> [a] -> [a]
trans _ = toList . (fromList :: [a] -> t a)
として、trans (Wrap :: Wrap T1) x yみたいに使う
ちょっとトリックを弄すれば言語拡張なしでも書ける
data (Trans t) => Wrap1 t = Wrap1
trans1 :: Trans t => Wrap1 t -> [a] -> [a]
trans1 w = toList . f w . fromList
where
f :: Wrap1 x -> x b -> x b
f _ = id
>>259 実現するには、今の Haskell(GHC)では無理矢理やるしか方法が無いんですね。
GHC の拡張機能で、もっとこう特別な構文なんだと一目瞭然な記述で、
スマートに型を伝える手段があるのかなと思ってました。
ソースを見た時に、なぜそのような記述になってるのか
意味を理解しにくくなりそうですね。
今回は QuickCheck 用のソースで、どのようにテストしているか、
その内容を分かりやすくソースで示す必要があるので、
今回は諦めることにしました。
せっかくのアドバイスですが、すいません。
262 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/20(土) 09:27:50
tsuwabukiてめえこいよ haskell板のtsuwabukiっていうやつがSkypeにきたぞ
263 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/20(土) 10:48:49
メンバー募集中です
募集要項
1、暇人+1日1回、2chの書き込みができるかた
2、プログラミング経験あり 言語はPerl,Ruby,PHP,Python
3、絵がうまいかた 素材をつくれるかた
4、情報発信が得意なかた
これに当てはまる人ははいれます
主な活動
1、ネットゲームでの全てのゲームにおいての共通ギルドを作り活動
リネージュ、アイラ、マビノギ、アナザーデイなどその他、メンバーがやるゲームすべて
ギルド名はゲームエンペラーズ
2、各ゲームの攻略サイト、wikiなどウェブサービスの作成
3、2chへの書き込み 共有コテ可 自分で好きなコテつくって活動してくれてもあり
4、資本金3000円
Skype: perlkage
http://hibari.2ch.net/test/read.cgi/tech/1284704280/ にご連絡ください
いいかげんこのアホ忍者通報されないかな Haskellスレと無関係なことばっかじゃん
>>261 積んでたが、これから読んでみる
書評は2、3ヶ月待ってくれ
途中で色々質問するかもしれん
268 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/21(日) 19:46:38
う
269 :
Perl忍者 ◆M5ZWRnXOj6 :2010/11/21(日) 19:53:46
ん こまねち
>>267 進化論は板違いだろ
しかし、このスレの奴は進化論が好きだな。
こういう書き方ってできないんだな hoge [] = error "hoge: empty list" hoge = head . tail せっかくポイントフリーで綺麗に読みやすく書けたと思ったのに、 エラー処理を入れたとたんに仮引数を明示しなければならないなんて
>>267 忍者はスルーで”カルト”には反応しちゃうんだ....
274 :
tsuwabuki :2010/11/23(火) 10:27:28
Haskellやってますが アルバイトで生計たててます
「Pearls of Functional Algorithm Design」を読み直してるんだが、 やはり 15 ページ目で躓く。 真ん中辺りで Jack が Consider an m x n rectangle and let T(m,n) denote the number of evaluations of f required to search it. と言っているが、この最後の it は何を指してるんだ? つまり T(m.n) は何を探すのに必要な f の評価回数なのかが知りたい。 これが分からないから、すぐ下で述べている、 m=0 や n=0 の時に検索の必要がないという意味も、全く分からないんだ。
その本読んでないから見当違いかもしれんが、m x n rectangleの事じゃないの。
>>276 >>277 ありがと
> search Xの意味は「Xを探す」じゃなくて「Xから何かを探す」
マジですか!
今まで生きてきて、X を探すという意味しか無いとずっと思い込んでた。
from の意味が暗黙的に含まれている事もあるのか、目から鱗だ。
英語って奥が深いな・・・
認識を改めてちょっと読み直してみる
>from の意味が暗黙的に含まれている事もあるのか 辞書を引けば分かるけど常にこの意味だよ 「X(物体)を探す」ならsearch for X
うそん search a needle in a haystack とか言わないか
>>279 認識を新たにして読み直してみたが、そうすると今度は直後の
If m=0 or n=0 then there is nothing to search.
が疑問なんだが、もしかしてこれも「探す対象がない」のではなく、
for が無いから「探す範囲がない」と言っているのか?
それでもおかしいな。
例えば m=0 でも、f(0,0) から f(0,z) まで探す必要があって、
(0,0)-(0,z) までが検索範囲になると思ってるんだが、勘違いだろうか。
(正確にはもう少し範囲を狭められるという話題が直前にあったが)
>>282 > m x n rectangleと言ってるんだから、mとnは座標じゃなくてサイズだろ
それなら、「探す対象はたぶん「f (x,y) = zを満たす(x,y)」じゃね」と矛盾しないか?
例えば f(0,0)=z だったら、探す対象は (0,0) のはずなんだが、
それは幅 m 高さ n の rectangle の範囲のどこにあるか
と考えた時に「アレ?」って思わない?
なんか、俺が何か大きく勘違いしている気がするんだが・・・
>>277 で読める分だけ読んだけど、別に矛盾しないような
探索範囲である長方形を再帰的に分割・縮小していくアルゴリズムで、
その過程で現れるサイズm*nの領域を探索するコストの話をしてるんだから、おかしいところはないはず
>>284 例えば、f(x,y) が次のような狭義の単純増加関数だったとする。
f(0,0)=5, f(1,0)=6, f(2,0)=7 ...
---------
f(0,1)=6, f(1,2)=7, f(2,3)=8 ...
---------
f(0,2)=7, f(1,2)=8, f(2,2)=9 ...
このような関数で f(x,y)=6 の (x,y) を探すとする。
分割統治で探す範囲を f(0,0)、f(1,0)、f(0,1)、f(1,1) の範囲に絞り込めた時、
Jack の言う m x n rectangle というのは幅 1 高さ 1 ではなく幅 2 高さ 2 なの?
直前の Mary の発言では、検索の範囲は top-left corner (u,v)、
bottom-right corner (r,s) と表現されていて、f(u,v) ではなく
真ん中の f(p,q) から探し始めてはどうかと提案している。
普通こういう場合の幅って r-u や s-v なんじゃないの?
>>285 ごめん、例のパラメータ値がおかしかった
f(0,0)=5, f(1,0)=6, f(2,0)=7 ...
---------
f(0,1)=6, f(1,1)=7, f(2,1)=8 ...
---------
f(0,2)=7, f(1,2)=8, f(2,2)=9 ...
関数fから2つの値を返して それらにletで一つずつ変数を束縛したいのですが どんな風に書けば良いでしょうか?
f = (1,2) ff = let a = fst f b = snd f in [a,b] みたいな?
f = (1, 2) g = let (a, b) = f in (aとbを使う式) で束縛できるでしょ。
ありがとうございます。
>>288 なるほど、どうも以前やってた言語のイメージで
「2度呼び出されるのはマズいのでは」と感じてしまって
let tmpList = f
in
let
a = fst tmpList
b = snd tmpList
in ...
みたいなことを考えてしまいました。
でも Haskell の場合、引数が同じなら結果も同じ…と考えれば
そんなことは杞憂かも知れませんね。
>>289 そんな書き方が出来たのですね。
タプルは失念してました。精神的にも良い感じなのでこっちで行こうと思います。
>>290 仕様上は保障されていないと思うけど、WinGHCiで
Prelude> :m + Debug.Trace
Prelude Debug.Trace> let bar = let {foo = "eval foo" `trace` (1,2); a = fst foo; b = snd foo} in a + b
Prelude Debug.Trace> bar
eval foo
3
となったので、少なくともこの単純な例の場合、ghciではfooは一回しか評価されないみたいね。
しかし、次の場合は二回評価される:
Prelude Debug.Trace> let bar = let {foo x = "eval foo" `trace` (x + 1, x + 2); a = fst $ foo 0; b = snd $ foo 0} in a + b
Prelude Debug.Trace> bar
eval foo
eval foo
3
で、次の例だと一回しか評価されない:
Prelude Debug.Trace> let bar = let {foo x = "eval foo" `trace` (x + 1, x + 2); (a, b) = foo 0} in a + b
Prelude Debug.Trace> bar
eval foo
3
結論としては、「いろいろ考えるのは面倒なので、
>>289 方式」で良いと思う。
>>291 それは、書籍なんかでもよく取り上げられるトピックなんだが、
同じ関数を同じ引数値に適用しても、そのつど評価されるんだよ。
同じ引数値だからキャッシングされてるだろうと考えてはいけない。
それはプログラマ自身がキャッシングの仕組みを作る必要があるんだよ。
一般になんていう名前のテクニックだったかな、忘れてしまった。
キャッシングじゃなくて、もっと別の名前があったような気がしたが。
memoize のことか?
そう、それだ memoize って発音しにくいよな
処理速度の測り方にいまいち自信がないんだが、 例えば次のプログラムで concat 関数の処理速度を測ったことになる? time :: IO () -> IO Float time p = do st <- getCPUTime p et <- getCPUTime return $ fromIntegral (et - st) / (10^12) main :: IO () main = do let !l = take 1000 $ repeat (take 1000 $ repeat 1)) t <- time $ do let !i' = concat l return () putStrLn $ "time : " ++ show t ++ "s"
ならない do let !i' = concat l; return () は concat l `seq` return () と等価だけど、seqは左辺を最上位の構築子が明示される形(WHNH)までしか簡約しない。この例だと、 concat (take 1000 (repeat (take 1000 $ repeat 1))) を 1 : 何か まで評価したらそこで終わってしまう
>>296 やはりそうか
だからリストの要素数を極端に増やしても 0.0s のままなんだな
let a = concat l
let !b = length a
と
let !b = length l -- (l は concat 済み)
の2つの処理の前後時間の差分を測り、さらにそれらの差分を測れば、
concat の処理速度を測れたと考えていい?
オレは、
>>296 とは別人物ね。
たしかに、そういうような比較をすれば、ある意味では、concat の処理速度を測れたといってよいと思う。
「ある意味では」というのは、動的なメモリ確保とか、遅延評価のクロージャを処理するコストも測定結果に含まれてしまうけども、ということ。
ただ、オレもそういうことを以前は気にしていたけど、いまはそのような評価はあまり意味がないんじゃないかと思う。
なぜなら、concatの処理速度をそのように計測したところで、実際のアプリケーションではどうせ遅延評価されるわけで、その「concatのコスト」がまるまるアプリケーションのコストになるかどうか分からないから。
もし、特定のアプリケーションで、何かの処理をするまえに必ずconcatの結果をすべて評価しておきたいとかいうことであって、しかもその処理速度が気になるようであれば、
リストのような遅延評価向きのデータ構造とか、concatのような遅延評価前提の関数を使うんじゃなくって、
正格データ型とそのための専用関数を用意するべきじゃないかと思うんだ。
299 :
298 :2010/11/29(月) 02:28:00
例えば、こんな感じ。 data List a = Cons !a !(List a) | Nil deriving Show concat' :: List (List a) -> List a concat' Nil = Nil concat' (Cons Nil tt) = concat' tt concat' (Cons (Cons h t) tt) = Cons h (concat'' t tt) concat'' :: List a -> List (List a) -> List a concat'' Nil tt = concat' tt concat'' (Cons h t) tt = Cons h (concat'' t tt) -- テスト用の関数。 -- 次のようにghciなどで評価すると明らかにかかる時間が違う。 -- test 100 100 `seq` () -- test 1000 1000 `seq` () test :: (Num a) => Int -> Int -> List a test x y = let {l = take x $ repeat (take y $ repeat 1); f = foldr Cons Nil }in concat' $ f .map f $ l
>>298-299 非リアルタイム3Dレンダラーを分割統治法で書いてる。
イメージを縦横いくつかのブロックに分けてそれぞれレンダリングし、
最後にそれらを一つのイメージに合成する。
で、合成する時に、Array ブロックから Array 単体に合成した方が速いのか、
List ブロックから List ブロック 単体か、Array ブロックから List 単体か・・・
その時に使う合成戦略(関数の使い方など)はどれが速いのか・・・
といろいろ実験してた。
> いまはそのような評価はあまり意味がないんじゃないかと思う。
最初 Array で単純に合成しいてたら、合成処理時間だけでけっこうかかってた。
正格に何ミリ秒かかったとかいう数値はそれほど必要ないけど、
レンダリング全体の時間に対する割合くらいはパーセンテージで欲しいんで。
> 必ずconcatの結果をすべて評価しておきたいとかいうことであって
すまん、まだ遅延評価しておかなきゃならないんだ。
合成後もそれを一部テクスチャにして別のレンダリングをしたりするから、
無駄なレンダリング処理を省きたい。
ただ、正格評価用のデータ構造と関数を別に用意しておくという考え方は参考になった。
別の部分の処理で絶対に必要になるから覚えておく、ありがと。
データ型を受け取って同じデータ型を返す関数を次々に適用した場合の最適化について質問です。 次のようなデータ型と、それを使った関数があるとします。 data T = T Int Int f (T x y) = T (x*2) (y*3) この関数を次のようにして使った時、 a = T 1 2 b = f (f a) 一度目の f の出力値を作る所から二度目の f の入力の間にかけて、 データ型を被せてすぐに剥がすという無駄なことをしているので、 次のように最適化される嬉しいのですが、 b = T (1 * 2 * 2, 2 * 3 * 3) 特に何もしなくても自動的にこのように最適化されるのでしょうか。 あるいは、書き換え規則(RULES)のような 何かコンパイラへのヒントを与えれば自動的に最適化されるのでしょうか。 それとも、自動的には不可能でしょうか。 コンパイラは GHC 6.12.3 を使用しています。
>>301 -ddump-simplオプションで最適化済みのGHCの中間コードが見られる
その例のままだと、fが小さい関数だから-Oでインライン化されてb = T 4 18まで最適化される
インライン化できないほど大きいfの場合でも、worker/wrapper変換という最適化がかかるから
すぐ捨てるような中間データは排除してくれることが多い
f (T x y) = T (x+x+x+x+x+x+x+x+x+x+x+x+x+x) (y+y+y+y+y+y+y+y+y+y+y+y+y) とか、インライン化しない例
>>302 -ddump-simpl-stats オプションを付けてコンパイルした時、
RuleFired の項目に worker/wrapper が無ければその最適化は効いていない、
つまり中間のデータ型は無駄に構築されているという判断でいいでしょうか。
>>304 worker/wrapperはRule(書き換え規則)じゃないから関係ないはず
>>305 最初 -ddump-simpl しても何も出力されなかったから、
とりあえず最適化されたかの目星を付けようとして
>>304 と訊きましたが、
今分かりました。
-ddump-simpl の出力を見て、例えば
>>301 の例だと、
b が参照している T の中身を辿っていった先が定数になっていれば、
最適化がちゃんと働いたということですね。
UArrayからByteStringへの変換の効率の良いやり方ってありますか? つまり、 > uArrayToByteString :: UArray Int Word8 -> ByteString > uArrayToByteString a = pack . elems という関数を、リストを経由しないように実装したいんですが。
uArrayToByteString :: UArray Int Word8 -> ByteString uArrayToByteString arr = fst $ unfoldrN size f first where (first, last) = bounds arr size = last - first + 1 f k | last < k = Nothing | otherwise = Just (arr ! k, k + 1) こんなもんかな?
{-# OPTIONS_GHC -fglasgow-exts #-} import Data.ByteString.Unsafe(unsafePackAddressLen) import GHC.Prim(byteArrayContents#) import System.IO.Unsafe(unsafePerformIO) uArrayToByteString :: UArray Int Word8 -> ByteString uArrayToByteString arr = let !(UArray _ _ n barr) = arr in unsafePerformIO $ unsafePackAddressLen n (byteArrayContents# barr)
>>309 それは駄目だろ
第一にpinされていないByteArray#に対してbyteArrayContents#を使っているのでGCでbarrが動いたら終了
第二にunsafePackAddressLenは呼び出し側がメモリを管理することを要求するけど、
それを怠っているのでbarrがGCに回収されたら終了
311 :
309 :2010/12/03(金) 23:02:34
>>310 UArrayとByteStringは内部表現同じっぽいし
ゼロコピーでいけるんじゃね?と思ってでっちあげてみたんだけど、
やっぱりGCでこけるか。
いやまあ、そんな気はしてたんだけど。
初歩的な質問で申し訳ないですが、 sum . map (2^) $ [0..9] sum $ map (2^) $ [0..9] sum $ map (2^) [0..9] これらの違い(コスト?)を教えてください。 そもそも$演算子のありがたみが(カッコが減る以外に)思いつかないのですが、 Real World Haskellの索引をみても($)はfmapのところに飛ばされるだけで、 どこに解説してあるのか不明です。 よろしくお願いします。
>>312 違いはないと思っていい
最適化しない処理系だとコストが微妙に違うけど、sumとmapとenumFromToのコストに比べたら無視できる
>そもそも$演算子のありがたみが(カッコが減る以外に)思いつかないのですが、
基本的にそれだけ
あとは高階関数に($)を渡すとか
>>312 括弧が減るのは結構ありがたいよ。試しに全部括弧で書いてみるといい。
( はまだその場で書くからいいが、
) はまとめて書くことが多くなるから、数を数えながら書かなきゃならなくなる。
まあエディタの対括弧表示の機能で何とかなるっちゃあなるんだが…
括弧の数で有名なLisp系は実際エディタで何とかしてるみたいだし。
そんな方法で括弧減らしてたら関数型使う意味なくね
>>315 は括弧を書くために関数型言語を使ってるの?
そうだよ
318 :
312 :2010/12/06(月) 16:59:21
>>313 ,314
ありがとうございます。ひとまず腑に落ちました。
>>317 Lisp使うと幸せなんでしょうね。
319 :
312 :2010/12/06(月) 19:18:13
でも、これってコーディング規約をつくらないと、
他人のを読んだときに混乱しそう。
みなさんはどういう規則で$を入れていますか?
それを規約として定義できますか?
>>312 の例だとmap一発ですが、二発三発なめる場合は
合成を使った方がいいようにも見えます。
320 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/06(月) 20:02:31
かわいそう・・・
どれでも普通に読めるので統一されてなくても気にならないけど、一応俺のスタイルはこんな感じ - 括弧の代わりに$を使えるならなるべく使う - 複数行にわたる括弧を消せるときは必ず使う - 見た目の対称性のために$を使わないことがある(「mappend (f x) (g y)」みたいな場合 ) - 必要のない$は使わない(例えば「f $ g $ x」の右側の$) - $の左辺に関数合成を置かない(例えば「f . g $ x」)
>>315 ,317
/⌒ ⌒\ ━━┓┃┃
/(  ̄) (_)\ ┃ ━━━━━━━━
/::::::⌒(__人__)⌒:::: \ ┃ ┃┃┃
| ゝ'゚ ≦ 三 ゚。 ゚ ┛
\ 。≧ 三 ==-
-ァ, ≧=- 。
イレ,、 >三 。゚ ・ ゚
≦`Vヾ ヾ ≧
。゚ /。・イハ 、、 `ミ 。 ゚ 。
>>319 そんなに混乱しないと思っているので、基本的に気分次第。
ただ、その気分次第の結果として、最も大きな式(?)の最後の括弧を減らせるかぎりは$を入れ、そうでないときは入れない、という傾向があると思う。
例えば
... = f1 (f2 (f3 a)) というときは
... = f1 $ f2 $ f3 a にしがち。
... = f1 (f2 (f3 a)) b のときは
... = f1 (f2 $ f3 a) b と書けはするけど、それはあまりしない。
> - $の左辺に関数合成を置かない(例えば「f . g $ x」) 以外はこっちと同じ方針だ
>>312 カッコを減らす以外にメリットはないでよ。$なかったらLispみたいになっちゃうから、
俺は結構好き。
関数名が長くなりすぎるのは設計が悪いんかなあ。 getNthHogeOfHageInHige みたいな。
data D = A Int Int | B String String x :: D で、x が B String String であることがわかっているときに、 f (case x of B s _ -> s) というのをもっと簡便に書くにはどうしたらいいでしょう?
>>325 一概には言えないが、関数型言語の関数(function)は、
手続き型言語の手続き(procedure)とは違って静的なものなので、
たいていは動詞ではなく名詞を使うように頭を切り換えると良い場合が多い。
だから、「get」「put」「set」「conv(ert)」などのような動詞が
なるべくなら接頭辞として付かないような方向で考える。
また、修飾語句はできる限り引数の型で表した方がスッキリする。
例えば「n番目の」というのは標準ライブラリを見ても関数名には無いと思う。
同じ役割の関数で番号指定できるものとできないものが有るなら、
(必要なら)私なら関数名の後ろにNを付けるか付けないかで区別するが、
その前にそもそも番号指定版だけで済ませられないか考える。
「〜の中の」とか「〜の」というのも、まず引数の型で表すことを考える。
「〜」に当たるものが色々あるのなら、それらをひとつの型クラスで表し、
その型クラスに対する「の中の」関数だけの状態にして、
関数名には「〜の中の」という言葉は入れないようにする事を考える。
「〜の中にある〜の中の」というように入れ子状に続くのは論外。
この場合は関数をいくつかに分けて、ひとつの関数で「〜の中の」は
多くても一つだけの状態にするように考える。
ただ、分けたそれぞれの関数が独立では使われず、
いつも「〜の中にある〜の中の」という状態で使われる場合は、
関数を分けずにひとつの関数で表して、
関数名としては一番外側の「〜の中の」だけを表した方がいい。
しかしこの場合、そもそも設計がおかしいことの方が多いが。
>>326 data D = A Int Int | B { foo :: String, bar :: String }
f (foo x)
329 :
326 :2010/12/07(火) 13:14:04
>>328 あぁぁ、フィールドラベルっていうのはそんなふうに使うのですね。
よくわかりました。ありがとう。
>>327 大変おもしろく読んだけれど、ここは気にいらない。
>その前にそもそも番号指定版だけで済ませられないか
常に要求された通り、または、心に浮かんだ通り、
定義するのが基本だと思う。
331 :
327 :2010/12/07(火) 18:11:06
>>330 そりゃ考え方は人それぞれだ。
ひとの考え方と自分の考え方の何がどのように違うのか、
何故違うのか、互いの色んなケースでのメリット・デメリットは何か、
色々比較した上でそっちの方がいいと思うのならそれでいいんじゃないか。
332 :
327 :2010/12/07(火) 18:54:04
今ふと思ったが、番号指定版と指定しない版が必要なら、 「指定しない版だけ」を作る方針の方がいいかもしれない。 順序付き集合を返す「番号を指定しない版の関数 hoges」と、 「何かの順序付き集合から特定番号の要素のみを返す関数 pick」に分ける。 例えば3番目の hoge が欲しかったら pick 3 hoges と記述する。 そうすると、pick 関数は他にも流用できるし、関数名を短くできる。 また、式を右から読んでいって何を表す式なのか、 比較的分かりやすいんじゃないかな。 これなら、番号を指定する必要がない時は hoges だけでいいから、 「常に要求された通り、または、心に浮かんだ通り、定義」できると思う。
333 :
デフォルトの名無しさん :2010/12/07(火) 20:07:15
f . g $ x これ良くないの!? 寧ろ積極的にこう書き換えてた!
状況による。 どの書き方がわかりやすいかは一概に言えない
状況というよりスタイルじゃないか? どの状況でどれを使っても大差ないよ
状況によっって使い分るスタイルかもしれんじゃないか
>>333 単なる好み(カッコよく言えば哲学)の問題だ。
私の場合はその書き方は気持ち良くないと感じる。
どちらかと言えば f (g x) の方が気持ちいい。
なぜなら、関数 f が適用するモノが分かりやすいと感じるから。
でも、その差は微々たるものだ。
そもそも、「分かりやすさ」というもの自体が個人の物差しであって、
その物差しをチーム内で(たいていは強引に)揃えるのが「コーディング規則」だ。
個人でプログラムしてるのなら、好きにすればとしか言いようがない。
f . g $ x は自分なら、あとでポイントフリーにしたいけど、 わかりやすさのためにまず変数を書いておくときに使うかな。 書き終わったらこの形は残らない。
>>338 後でポイントフリーにするのはどうして?
仮引数が残っているよりも、ポイントフリーの方が
分かりやすかったり、見やすかったりするから?
もしそうなら、それは「わかりやすさのためにまず変数を書いておくとき」
の場合の「わかりやすさ」とは違う質のもの?
関数定義で複数のパターンマッチがある場合、引数の数を揃えなければならないからとか?
>>339 書くときと読むときのわかりやすさが違うのかも。
書くときは仮引数xをデータとしてそれへの関数適用で考えて、
読むときは型宣言を手掛かりとしつつ右から左へ合成された関数の流れを見る。
だから、完成して型検査を通ったら、読みやすいようにポイントフリーにして
書き終わる。(左辺のxと、"$ x"を削除する)
はじめからポイントフリースタイルで書くのはちょっと難しい。
>>341 > 読むときは型宣言を手掛かりとしつつ右から左へ合成された関数の流れを見る。
ポイントフリースタイルだからこその分かりやすさというのが、
この説明ではまだよく分かんないな。
これなら最後の $ x が有っても無くても大して変わらなくない?
> はじめからポイントフリースタイルで書くのはちょっと難しい。
つまり逆で、最後にわざわざポイントフリーにしなくてもいいんじゃない?
長い式を書くときに、左から書いていける人か、右から書いちゃう人かで違うとか
344 :
342 :2010/12/08(水) 07:56:31
そういう私もポイントフリーを多用してるけど、 それは初めからポイントフリーで考えている時だけ。 関数作成を考え始める時点で、どのような役割の関数か、 つまり「何から何への写像」を作ろうとしているのかは分かってる。 これがメイン引数となる。 それを実現するのに必要な情報、サブ引数も洗い出せば分かる。 写像の形を元に、どの関数をメインに使って実現させるのか方針が立てられる。 (map なのか、filter なのか、その組み合わせなのか、既存の自作関数かなど) この時点で自然にポイントフリーで考えてる。 (ポイントフリーにできない場合も、ごく自然に非ポイントフリーで考えてる) あとは、サブ引数を使って肉付けし、ソースを記述する時点では、 ポイントフリーになってる。 あとからポイントフリーにリファクタリングするケースはほとんどない。 そういうケースは自分の設計力の無さに多少落ち込む。
Eulerが見たらなんて言うだろう
おいらにゃ関係ねぇ
>>344 自然にポイントフリーで考えてるってのは「関数型脳」が既に身についているってことでしょ。
俺も初めは
>>342 みたいに、関数を書いた後からポイントフリーに
直してみるってことをやってたよ。
手続き型言語に慣れた脳味噌には、初めから関数合成で考えるのはちと難しいんだよね。
だから、まずは手続き的に「値を順番に変形させていく過程」として捉えて関数を書いてから
後からポイントフリーにすることで、改めて関数合成として捉え直してみるっていう感じだな。
そういう修行wを通じて、段々と「自然にポイントフリーで考え」られる脳味噌が
できていくんじゃないかな。っつか、俺の場合はそう。
351 :
デフォルトの名無しさん :2010/12/09(木) 01:59:40
グーグル検索 ↓ 念のためうぷ(´・ω・`)まわいが重要 グーグル検索 ↓ やらなくてもやられるし 日本語以外話せないし テレビやネットで説明
>>350 そういう関数型と手続き型を比較しつつ、
関数型の思考法を徹底的に解説する本があれば面白そうだ。
関数型らしさとは何か、と複数の著名人にインタビューした記事とか。
「Introduction to Functional Programming(関数プログラミング)」や
「Fun of Programming(関数プログラミングの楽しみ)」などは
そういうのとはちょっと違う感じだった。
(後者はわりと近いが)
>>350 俺も未だに手続き脳なんで、すごく解る。
「自然に書く」と、およそポイントフリーには向かない設計になってるんよね。
流れを切ってすみません。 Haskell 98 Reportの3.11 リスト内包表記で、 [ x | xs <- [ [(1,2),(3,4)], [(5,4),(3,2)] ], (3,x) <- xs ] が [4,2] になるという例が載っています。 で、この「3」を変数として与えられるようにしようと、 (\y -> [ x | xs <- [ [(1,2),(3,4)], [(5,4),(3,2)] ], (y,x) <- xs ]) 3 とすると、内包表記内でyのスコープが別にできてしまい、 結果が [2,4,4,2] になってしまいます。 とりあえず、ガードをつけて、 (\y -> [ x | xs <- [ [(1,2),(3,4)], [(5,4),(3,2)] ], (z,x) <- xs, z==y ]) 3 とすれば、望みのことができますが、こうするしかないものなのでしょうか?
名前変えればいいだけじゃん。 なんで y にしたいの
>>355 そうするしかない
内包表記に限らず動的にパターンを作る方法はない
>>356 えっと、意味がよくわかりません。
>>357 ありがとうございます。そういうものなのですね。
パターンは静的にしか書けないという規則だと思えば、すっきりしました。
・パターンは静的にしか書けない
>>359 は将来、過去を振り返って、いろんな意味で恥ずかしく思うんだろうなぁ
金言と間違えてないか。
362 :
359 :2010/12/10(金) 05:30:23
いつのまにか Haskell.org のサイトが刷新されてた
金言というより格言かもしれんが、Haskell でプログラムする上で 私が心に留めているのは次の言葉。 「時間を空間に」 自分でこれに気づいた時は「俺すげー」と革命が起きた感じだった。 後で調べてみると、誰もが当たり前のように考えた事だと分かったが、 これが Haskell の本質だと確信を得た感じで逆に嬉しかったな。
kwsk
>>365 たとえば、2つの計算 A と B が有るとする。
A を計算し、その結果が x だったらそれを使用し、
もし結果が y だったら B の計算結果を使用したい。
他の言語なら、A の後で B を計算する様に、逐次的に見える様に記述するが、
Haskell なら A と B を同時に計算する様に、宣言的に見える様に記述する。
それはリストに羅列されていたり、演算子で結合されていたりと、形は様々だ。
で、A と B のどちらが必要になるかはたいてい別のところに記述する。
B が不要なら実際には計算されない。
つまり、時間的な流れに沿った計算を空間に広げて「一望できる」ようにする。
これが遅延評価の為せる業であり、宣言的に記述できる Haskell の特徴だ。
これは一例だが、時間の流れを空間の広がりに換える考え方は、
Haskell プログラムの至る所で役に立つ。
Algorithm = logic + control
>>366 逐次的に見えるっていうか現実に逐次的だよね。
現実に沿った計算を、非現実的観点で一望することにどういう意味があるの?
>>368 > 逐次的に見えるっていうか現実に逐次的だよね。
ちょっと違う。
現実のものを逐次的視点で捉えるか全体を一度に捉えるかの違いであり、
どちらが分かりやすいかは時と場合と「好み」による。
Haskell は後者の様に捉えた方が分かりやすい問題を綺麗に記述できる。
また、「一見」前者の様に捉えた方が分かりやすかった問題を、
後者の様に捉え直すことで、Haskell で扱いやすくする。
> 現実に沿った計算を、非現実的観点で一望することにどういう意味があるの?
計算Aはどのようにするのか、ではなく、計算Aとは何か、
という構造が分かりやすく(見やすく)なる。
(繰り返すが、後者の方を好む人にとって分りやすくなる)
例えばパーサーなら、X := A | B というバッカス記法をそのまま記述できる。
Aを読み取って失敗したらBを読み取ったものがXだと逐次的に捉えるのと、
XはAまたはBだと全体を一度に捉える違いだが、後者の方が一望できて分かりやすい。
分割統治も全体を一度に捉えた方が比較的分りやすい例だと私は思う。
わざわざ道具を使うために問題を変質させているようにしか見えないのだが 例が悪いのか?
>>366 データフローや並列計算の話をしたら喜ばれそうだけど
Haskellの本質とやらはそっち方向にはなさそうだよ
無限集合をわざわざ空間と時間の置換で説明するのか。素晴らしい金言だな。
賛同者がいっぱいいると思ってたんだが、なんかずいぶん否定的だな。 私も Haskell 歴はまだ1年とちょっとでかなり浅いから、 みんなを黙らせる良い例を挙げられないのが悔しいが・・・ 時間と空間という言い方がまずかったのかな。 相対論的な意味での時間と空間の置換という意味では決してないんだ。 ではこう言ってはどうだ? 「動を静に」 手続き型言語なら時間軸に並べられた計算を動的に捉えて書くけど、 Haskell ならそれらの関係性を静的に一度に捉えた方が扱いやすくないか? FRP による GUI ライブラリなんか正にそんな感じに捉えてるような気がするんだが。
>「動を静に」 それなら良く分かる 手続き的か宣言的か、という奴だね
>動を静に これなら感覚としてはまあ分かる でも金言って程ではないかな
>>374 >>375 そうなのか
ただ、やっぱり私の中では時間的に考え方を空間的に捉え直す方が
しっくり来るというか、「動を静に」よりももう少し意味が広くて、
関数型の中でも遅延評価デフォの Haskell らしい感じが秘められてると思うんだが。
宣言的なら他の関数型でも普通にやってるし・・・
まぁいいや。
あまり盛り上がりそうな話でもなかったと言うことで、消えます
>>373 それを、一言でいうと「数学と同じ」だと思うんだよね。だから、誰もわざわざ指摘しないというか。
諸君、素晴らしい議論だ。
>>377 なんでそういう大事なことを入門書では教えてくれないんだろうな。
入門するには頭を切り換える必要があると著者は分ってるはずだが、
何を頼りにどう切り替えるのか、本質は何かを解説しないで、
文法やケーススタディばかり解説する。
数学は定常状態を仮定しますが、教育や計算は過渡現象だからです
>>380 は
>>379 に対するレスなのか?
いまいち意味が分らんな
教育と言えば、今の Haskell の入門書って、微分積分を使わずに
運動方程式の計算だけを教えて意味を教えない高校物理みたいな、
なんとも言えない気持ち悪さを感じる
あんたら、どっから沸くんだYO
>>382 こういう話が嫌なら、Haskell ブログラムのネタを振ってくれ
今は特に話題がないからダベってるだけだ
前から思ってたけどこのスレ結構人いるよな
>>383 STモナドは時間の流れを意識せずには書けないけれど、極めて純粋だよね
静なんだけど動なモナドだよね
この流れ的にはどうなの?
>>385 俺が知るかよ
STモナドが気持ちいいかどうかと訊かれれば、俺は気持ちよくはないな
避けて通れるなら避けたいところだ
STモナドを使うと気持ちよく表現できるアルゴリズムとか未だ知らんし
なにかある?
いくらでもあるだろ クイックソートとかQR分解とか
>>381 の続きだが
「虚数の情緒」みたいな、著者が可能な限り妥協しない、
分厚いが本質を丁寧に述べて Haskell の楽しさを思う存分語る、
そんな入門書があってもいいと思うな。
"Arrows for Invertible Programming" という論文を読んでたら、 「embedding-projection pair」というものが既知のものとして出てきたのですが、 どういったものか誰か知ってませんか。 どうも、embedding-projection でペアにするのは関数で、 それをこの論文では関数ではなく Arrow をペアにするアイデアを使ってるみたいなんです。 なんとなく、embedding-projection pair は、 a -> b という型の関数とその逆変換の b -> a という型の関数をペアで持つ、 という感じを受けたのですが、合ってるでしょうか。 これは元々どのような問題解決の文脈で出てきたものか、 知ってる人はいないでしょうか。 ちなみに、embedding-projection pair の参考文献は R. Hinze and S. Peyton Jones. Derivable type classes. In G. Hutton, editor, Proceedings of the 2000 ACM SIGPLAN Haskell Workshop, volume 41.1 of Electronic Notes in Theoretical Computer Science. Elsevier Science, Aug. 2001. The preliminary proceedings appeared as a University of Nottingham technical report. らしいので、ACM Digital Library 内を探しましたが、見つけられないです。
Haskellで、対話的なプログラムってどんな感じになりますか? 手続き的に書くと 1. 入力を促すメッセージを表示 2. キーボードから文字列を入力 3. 特定の文字列or文字列終端が入力されると終了 4. 入力された文字列に関数を適用 5. 適用した結果を表示 6. 最初に戻ってループ な感じのプログラムなんですが…
391 :
デフォルトの名無しさん :2010/12/12(日) 09:22:30
>>390 とりあえず書いてみた
module Main where
main = loop f
f :: String -> Maybe String
f ":q" = Nothing
f s = Just $ "input: " ++ s ++ "\n"
loop :: (String -> Maybe String) -> IO ()
loop f = do
input <- getLine
case f input of
Just output -> putStr output >> loop f
Nothing -> return ()
392 :
391 :2010/12/12(日) 10:14:29
sage忘れスマソ 仕様に完全には一致していなかったので書き直し: module Main where import System.IO main = do hSetBuffering stdout $ BlockBuffering Nothing loop "input any... " f f :: String -> Maybe String f ":q" = Nothing f s = Just $ "your input: " ++ s ++ "\n" loop :: String -> (String -> Maybe String) -> IO () loop msg f = do hPutStr stdout msg hFlush stdout input <- getLine' case input >>= f of Just output -> putStr output >> loop msg f Nothing -> return () getLine' :: IO (Maybe String) getLine' = do bool <- isEOF if bool then return Nothing else Just `fmap` getLine
どうすれば行頭にスペースを表示させられるのか、この迷える子羊にお教え下さい。
>>366 上手く言えないけど、無駄に話を難しくしてる気がする。
「時間を空間」にの「空間」の意味が曖昧でよくわからない。
っていうかそれHaskellの本質ってより、ただ高階関数と条件分岐を
組み合わせただけなんじゃ...?
396 :
395 :2010/12/12(日) 12:05:04
>>381 プログラミングHaskellは高校物理っぽくないという点で
結構いいと思うんだけど、どうよ?
>>366 ちゃんと続き読んでなかった。動を静にか。それは結構納得できるかも。
>>393 なるほど
「Proceedings of the 2000」や
「Proceedings of the 2000 ACM SIGPLAN Haskell Workshop」をキーワードに
ググってたから見つからなかったのですね。
ありがとうございます、助かりました。
haskell版processing作ったけど需要ある?
>>395 > 「時間を空間」にの「空間」の意味が曖昧でよくわからない。
空間は、結果的にはソースコード上の横方向の広がりだ。
縦方向の広がりが時間と考えてくれていい。
たとえば2つの図形A、Bがあり、これらを表示するアプリを作るんだが、
デフォルトではAの座標はBの座標系で表現されている。
しかし、ユーザーのメニューでの選択などで逆の場合も起こる。
つまりBをAの座標系で表現した方が扱いやすくなる。
時間軸に沿うなら、初めはAをBにする座標変換行列を計算して保存しておき、
メニューを選択した時点でBをAにする座標変換行列を計算して置き換えると考える。
そうではなく、AとBの関係性をソースコード上で一望できるように
空間的(ソースコード上の横方向の広がりに換えて)に考えるなら、
初めからAからBへの座標変換行列とBからAへの座標変換行列の
両方を計算してタプルやリストなどに格納しておくような記述をする。
図形(座標系)が複数合っても同じ。
互いの変換行列を最初に計算して、関係性をグラフで表しておく。
後で必要になった時にグラフのノードを辿って行列をかけ算していく。
これでイメージが少しでも伝わらなかったら、たぶん私の考え方が
どこか間違ってると思うので、しばらく頭を冷やす。
>>394 HTMLの実体参照。
つまり、「 」を入れる。
>>400 「時間を空間に」というと、破壊的に置き換えるイメージが伝わる
でも「時間だけでなく空間も」というと、両方を認めるマルチパラダイムになる
数学者にマルチパラダイムを与えるのは、ボクサーから拳を奪うようなものだ
404 :
395 :2010/12/12(日) 15:04:45
>>400 ふーん。やっぱり何かおかしいと思うよ。わかりやすくするために例を挙げるのに、
座標変換やらなんやらが出てくるのか。
結果的にソースコードの横が空間で縦が時間だと言うけれど、
hoge >> huga
と
do hoge
huga
が同じ意味になるという点についてはどうなんだろう。
しかも手続き言語でも、座標変換のルーチンは関数で定義するわけだから、
はじめから変換行列は(記述上では)計算済みということになるんじゃないの?
「動を静に」が納得できるのは、手続き言語では状態の変化の様子を
そのまま記述するのに対して、Haskellその他では、
ある状態が別の状態に変化するときの「間」を記述することが多いから。
状態そのものは「動」だけど、状態と状態の「間」は静だよね。
405 :
395 :2010/12/12(日) 15:38:39
>>400 >>369 を読んでちょっと言いたいことがわかったかも。
モナドのことを言ってるんだな。そのパーサーの例だけど、パーサーは処理の観点から
見れば、逐次的なものだけど、文法を定義したい人間としては静的に捉えたい。
人間から見ると逐次的な部分は重要じゃないから、逐次的な部分をバインド演算子に中に
隠すことができるモナドはとても強力。
でも、それ捉え方の問題じゃなくて、言語の抽象化能力のことだと思う。
オブジェクト指向では文法の問題もあって、パーサーを静的っぽく記述するのは難しい。
少なくとも「時間を「空間に」」の言い方は全く良くない。「空間に」変えるのではなく、
時間的な問題を「隠蔽する」、と言う方が正しいと思った。
手段が目的になっている奴ばっかりだなw
それが研究ってもんだよ
目的のために使える手段を選ぶんじゃない 手段を使えるようにするのが研究
諸君、素晴らしい議論だ
だが議論をするのが20年は遅かったな。
413 :
390 :2010/12/13(月) 00:44:43
>>391-392 ありがとうございます。とりあえず対話的に動くところを確認しました。
やっぱり元があまりに手続き的だけに、若干ややこしくはなりそうですね。
あとは出てきた1つ1つの要素を見ていって、詳しく見ていこうと思います。
414 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/13(月) 21:21:32
知的ぶってんじゃねえよ ごみめら
>>413 > やっぱり元があまりに手続き的だけに、若干ややこしくはなりそうですね。
んー… 手続き的な処理は、例外的な処理を詰め込んでいくと、いっきにややこしくなる。
>>390 の仕様だと、「3. 特定の文字列or文字列終端が入力されると終了」の部分。
こういうのは、自分が使うだけのプログラムなら、べつにわざわざ書く必要はなくって、終わればプロセスをKILLしちゃえば良い、例外がスローされたらそのまま死ねばよい、という考え方もできる。
そういうふうに割り切れば、プログラムはすごく単純になる。
でも、そういうときも綺麗にかっこよく終わりたいとなれば、面倒なことになる。
これは手続き型だろうと、関数型だろうと、どんな言語でも同じではなかろうか。
417 :
390 :2010/12/14(火) 00:58:39
>>416 あー、なるほど。
確かに例外処理含むとややこしくなりますね。納得です。
ghci でコピペすると落ちる脆弱性
ちょっとオレの妄想を聞いてくれ。 HaskellでFlash書けたら嬉しくね?
Flashなんて将来消える技術だろう
YHCのJavaScriptバックエンドとHTML5を組み合わせる方が近道じゃないか、良く知らんけど
424 :
420 :2010/12/15(水) 20:41:56
>>421 ,422
スティーブ・ジョブズ乙
でも、たしかに、HTML5も魅力的。
>>423 やはり、オレが思いつく程度のことは、すでに手を付けている人がいるんだな。
425 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/15(水) 22:40:21
ジーッ・・・ ここのスレよく脱線してますね
人生を脱線してる奴に言われたくないわ
427 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/15(水) 22:52:10
お前みたいなゴミよりまともだけどね てめえみたいなやつは自殺しろ
Haskell にほんの少しでも関係する話ができないのなら失せろ
429 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/15(水) 23:34:26
クズ同士死んじまえ
430 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/15(水) 23:36:38
おめえtsuwabukiぼうやかい?ww
* 名前 tsuwabuki
* 自己紹介 pi-calculus, CSP, lambda-calculus, haskell, erlang, HTML5, P2P, 料理作り(プリン・パンなど), 筍, 紅茶, サーバ運用, 自作サーバ, 電子書籍, iPhone, Android, Arduino, 変形合体ロボット, gumonji
http://twitter.com/iasija かすみてえだな
420 426 428はtsuwabukiだろうね
てめえは低レベルだからさっさとしね
431 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/15(水) 23:41:55
かわいそうだからここらへんにしといてやるか ごみめら ここのスレも荒れるしな
432 :
デフォルトの名無しさん :2010/12/15(水) 23:50:50
正格評価をさせるもっとも基本的 な言語要素がseq a bなのはなぜ なのでしょうか。force aがあって、 その場で、ただちにaを簡約するとなっ いれば、seqよりも一般的と思う。
force aとaは何が違うの?
434 :
デフォルトの名無しさん :2010/12/16(木) 00:39:02
let x = 「複雑な式」 と書くと、xに束縛されるのは、 この式の評価結果(42という整数 としよう)ではなく、簡約グラフ と呼ばれる一種の計算手順であると 入門者向けの説明ではなっている。 また、この式が42に簡約されるのは、 xまたはxを含む式をファイルに書き だすときである。 結果、つまり、ファイルに42が書かれる ことは間違いない。しかし、簡約グラフ が蓄積されるかもしれない。そこで、 簡約グラフの形成後、ただちにこれを 42に簡約する指示を与える術がプログラマ に与えることを考え、これにforceという 名前をつけたのである。 seq a bはこの弱いバージョンで、bよりもa が先に簡約されることしか指示してない。
>>432 その force a がいつ評価されるのか、ということを考えなくてはいけない。
例えば、
f a = let b = force a in 10
という関数の場合、そのforce aが決して評価されない結果、aも評価されない。
逆に、
f a = let b = force a in b
となっていれば、force a が評価される結果、aも評価されるけど、それなら
f a = let b = a in b
と書いても同じこと。
>>432 haskell普段あんま書いてないから文法的に怪しいが
もしそのforceがあったとしても
somefunc (force a) (force b)
がa→bの順に実行されるかは決まらない
(通常は遅延評価されるので文脈次第)
なので実行順序が決まらないその1引数のインタフェースでは役に立たない
>>434 そういうことがしたいならseqで十分
let x = 式1 in 式2
を
let x = 式1 in seq x 式2
にすればいい
>>439 かわいいね。実にかわいい。すごくかわいい。とってもかわいい。
>>439 日本的な「萌え」にする必要はないと思うんだが、もう少しどうにかならなかったのかと小一時間…
Geekそのものじゃねえか気持ち悪い
普通にカートマン
445 :
デフォルトの名無しさん :2010/12/16(木) 23:26:15
>>436 無意識に左から評価すると考えてました。
そのためのseqなのですね。大変よくわかりました。
>>437 ありがとうございます。
表面的な使い方としては、理解できましたが、
seqでの等価表現のところがまだ理解しきれません。
>>442 geekはhaskellに似つかわしくないなぁ。
もっとクールビューティなのがいい。
ギークっぽい言語って言えばperlだよね
残念だ すごく残念だ
utf-8 の1文字の文字コードを utf-32 の 32ビット文字コードに変換したいので、 hackage にある encoding ライブラリをインストールしようとしましたがエラーが出ます。 以下の方法を試みました。 1. hackage から encoding-0.6.3.tar.gz をダウンロードし展開する [c:\encoding]。 2. ネット上から nl_types.h と langinfo.h をダウンロードし、 encodingフォルダに入れる。 3. cabal install --extra-include-dirs=c:\encoding --extra-lib-dirs=c:\encoding メッセージは次の通り ------------------- Building encoding-0.6.3... ... [ 6 of 65] Compiling Data.Encoding.ByteSource ( Data\Encoding\ByteSource.hs, dis t\build\Data\Encoding\ByteSource.o ) Data\Encoding\ByteSource.hs:149:17: Not in scope: data constructor `State' cabal: Error: some packages failed to install: encoding-0.6.3 failed during the building phase. The exception was: ExitFailure 1 ------------------- こういう場合、未定義データ構築子 State はどうすればいいんでしょうか。 <環境> Windows 7 Haskell Platform 2010.2.0.0 (ghc 6.12.3 cabal-install 0.8.2 Cabal library 1.8.0.6)
巨大な戦場ヶ原ひたぎさんみたいなのが良い
>>448 それ多分mtl-2.0でStateモナドがStateT Identityの別名になったので壊れたんだな
encodingの作者に連絡して直してもらうべき
応急手当としてはencodingの.cabalファイルのmtlへの依存を<2.0に限定するとか
しかしencodingってwindowsで使えるのか? nl_langinfo呼んでるけど
>>448 text か utf8-string 使った方がいいと思う
>>450 State なんて自分で直接使うことは滅多にないので、
あれ? あったはずだがと思ってましたが、定義が変更されてたのですね。
拙い英語でバグレポートを出しておきました(ちゃんと伝わってるといいのですが)。
>>451 さぁ? 一応 cabal configure は通ったのでイケると思った矢先のエラーでした。
>>452 text ライブラリを使ってみたら、いともあっさりと目的が達成されました。
こちらでやることにします。
みなさん、ありがとうございました。
>>454 > ほらよ、童貞ども
純粋なのは良いことさ。
hsc2hs の #enum の説明では
http://www.kotha.net/ghcguide_ja/latest/hsc2hs.html -----
#enum 型, 構築子, 値, 値, ...
#constを使った複数の定義の代替となる略記法。
それぞれの値はCの整定数(例えば列挙値)の名前である。
この名前は、アンダースコアの次の文字を大文字にし、それ以外を小文字にし、
アンダースコアを取り去ることで、Haskellの名前として使われる。
-----
とあるんだけど、これって 例えば #{enum CInt, , AAA_BBB = 0} とやったら、
aAAbBB = 0 に自動的に変換してくれるんじゃないの?
やってみたら、AAA_BBB = 0 に変換されたんだけど、
もしかして説明には自分で名前を haskell 風に変換する「方針」が書かれてるだけ?
あと、C 言語のヘッダに書かれてる enum 型は自動では変換されない?
>>456 =で値を明示する形式だと変換しないよ(最初からHaskellでの名前だから変換する必要がない)
値を明示しない場合は、Cの識別子として値を取得した後に
Haskellの識別子として同じものを定義するので変換が必要
>あと、C 言語のヘッダに書かれてる enum 型は自動では変換されない?
それを(半自動で)やるのが#enum
例えば、
#include <stdio.h>
#enum CInt,, SEEK_CUR, SEEK_END, SEEK_SET
とすれば、seekCur, seekEnd, seekSetの三つが定義される
>>457 ありがと、試したらできた。
あと、次のようにやると非常に分りにくいエラーが出ることも分った。
#{enum CInt,
, AAA
, BBB
}
でも、この形であっても = を付けて値を明示すれば問題なく変換される。
こういう物だとして受け止めておくが、この仕様は訳分らん。
イヴの日も堂々と議論しろよ
みんなクリスマスにはマスコミに植え付けられたマニュアルどうりの行動をするよね。 できないやつは振りをするよね。
そういうレベルのケンカは小学校まで
では、イブらしく 魔法発動のプロセスが暗に Haskell プログラミングになっている ファンタジーな物語を小説にしようかと思ってるんだが
>>462 少女はマッチを一本すりました。
すると、なんと小さな炎の中にテーブルが現れたではありませんか。
「まぁ、なんておいしそうなご馳走!」
しかし、副作用はありませんでした。
少女はマッチを一本すりました。
すると、なんと小さな炎の中に優しそうな青年が現れたではありませんか。
「まぁ、なんておいしそうなイケメン!」
しかし、副作用はありませんでした、
少女はマッチを一本すりました。
すると、なんと小さな炎の中に大企業の人事担当が現れたではありませんか。
「まぁ、これでやっと就職口が!」
しかし、副作用はありませんでした。
イブの日の小さな贈り物でした。
おお神よ、この憐れな少女に一握りのunsafePerformIOを与え給え
465 :
462 :2010/12/24(金) 21:20:19
お前の才能に嫉妬した 遅延評価も頼む
スクルージが「どうして、いまさらこんな幻を見せるのだ」と尋ねると、 天使は同情の面持ちで「評価のときが来たのだ」と答えました。 スクルージは今までの自分を悔い、天使を見上げて問いかけました。 「私はやりなおすことができないのだろうか…?」 天使は同情の面持ちで「値を書き換えるのはバグのもとだ」と答えました。
洋書の各トピックの最初に、こんな感じの意味深い単文が載るよね
468 :
デフォルトの名無しさん :2010/12/24(金) 22:18:52
すみません Shift-JIS を扱いたいんですけど、やっぱり無理ですよね? 掲示板でAAとか表示したいです
>>468 Windows なら Win32API を使えばいい
他 OS は知らん
試したことないがぐぐったらCodec.Text.Iconvとか出たけど、これはどう
iconv使えば大半の文字コードへの変換が出来るよ。 でも最近のバージョンのghcだとそのままじゃビルドできなかったと思う。 例外周りが変わったせいらしい? 詳しくは覚えてないけどソース弄ってビルド通した記憶はある
javaのtomcatみたいにHaskellで書かれたコンテナ探してるんだけど、オモチャみたいなヤツしかないですよね tomcatもオモチャみたいだけど apacheあたりと組み合せないとダメでしょうか
474 :
デフォルトの名無しさん :2010/12/25(土) 08:35:06
パッケージインストールしようとsetupをghc --makeしようとしたら ldが馬鹿にメモリ確保してフリーズ?する Windows2000 SP4 CPU MMX Pentium 200MHz、 メモリ 96MBだから? i586CPUでも動くんじゃないの?
自分で解決できないやつがそんな古い環境使うのが問題
1時間くらい放って置いたら出来てた これはメモリが少ないせいかな
これ10年前のスペックだろ 3万もしないネットブックの方が遥か上のスペックだぞ
>>477 組み込みだと普通だと思うけど
Win2000を使ってるのはおかしいが
10年前にはもうすでにペンティアム4-2GHzが発売されていたらしい。
いま調べてたら、Haskell2010ってのがあるらしいけど、何これ?
ぼくのかんがえたさいきょうのげんご
Haskell 1.4 の次の Haskell 98 の次の仕様
先週ダウンロードしたGHCはHaskell2010ですか?
>>478 今時、組み込みでも300MHzていどは回さないとw
# まぁ、目糞鼻糞だが300MHzでx86-200MHzの倍程度のスピードはでる
SuperHとかハイスペックだな
リンクにバカほどメモリを喰うのって静的リンクしてることと関係あるの?
いいえ。
>>474 って、OSだけでメモリオーバーしてて、メモ帳起動してもフリーズすると思う
Parsec の質問です。 C 言語のソースから、宣言されている構造体を抽出するパーサーを作りたいです。 "struct aaa {...} bbb" という形の構造体そのものを解釈するパーサーは作れました。 しかし、その C 言語のソースは構造体以外にも余計な文字列があるので、 それらを「解釈しないで」省き、構造体だけを抽出したいです。 そういう場合は、まず正規表現で構造体部分の文字列を取り出してから、 それらをパーサーで解釈するという方法はあまりに拙いでしょうか? 構造体を表す文字列に出会うまで全ての文字列を捨てる、 というパーサーがなかなか作れません。 ghc 6.12.3 parsec 3.1.0
Cの型宣言部分は解釈しないと話にならんでしょ 関数本体とかは省略できるけど プリプロセッサとかどうすんのかね まあどうでもいいやねw
>>488 しないしない
確かにOSだけで既にスワップ起こってるけど
自動優先度変更アプリ使って調整すれば
音楽聴きながらgvimでプログラミングできるよ
MinGWでコンパイルもできる
LibreOfficeも超モタツキながらも何とか動く
ghc --make でパッケージのSetupからexeファイル生成する時特有の現象なのです
あるいは小規模のmakeしかしてないから知らないだけか
多分既にスワップ起こしてるのにさらに
50MB程スワップ膨らませてるからだと思う
CPU使用率は20%くらいがずっと続くのにレスポンスは100%並にモタつく
これって処理の殆どがハードディスクとのI/O待ちって事でしょ?
>>489 C言語のソースコードから自動でドキュメントを生成するツールがあるから、そのツールのソースコードを覗いてみればいいと思う。
>>491 コンパイルのときにガーベッジコレクションが頻発してるっていうオチか…
GHCもGHCでコンパイルしてるって話だったし
>>493 >>489 じゃないけど、構造体だけ抽出してスタブ作ってゲッターとかセッターとかの関数を自動生成したことならある
496 :
489 :2010/12/25(土) 22:17:13
>>493 >>495 と同じ知れない。
FreeType2 の Haskell ラッパーを作ろうとしてて、
構造体をデータ型で表現して Storable クラスのインスタンスにしたい。
正確には、hsc ファイル(の一部)を書くのを自動化して、
それで出力したコードを hsc2hs に入力する。
最初はライブラリ ドキュメントや C のヘッダーファイルを見て手作業でやってたが、
その構造体が比較的大きくて、量もそれなりにある。
ほとんど決まり切った形に変換していくのにイラついてきたから自動化させようと思って。
FreeType に限れば typedef struct AAA BBB; と typedef struct AAA {...} BBB;、
これだけ解釈できれば十分で、あとは手作業で楽に hsc ファイルが書ける。
本当は正規表現も使って本来の目的は達成できたんだが、
あまりにその場限りな感じの方法で、もっと洗練した方法があるか質問したかった。
>>492 探して見てみる、ありがと。
そういう場合、他言語だとswig使う。 今みたら、haskell用は無い見たいだけど、作ると喜ばれると思う。
>>497 それをするには、まず swig の仕組みから勉強しないといけないんだよなぁ
language-cを使って、foreign importをヘッダーから自動で作るやつは作ったことがある ただ、ASTがShowのインスタンスじゃないから、パースした後どういうデータ構造になるかチェックするのが大変だったけど
というか、gccのソースを見ればいいんじゃね? cのソースじゃなくてlexやyaccのソース
501 :
489 :2010/12/26(日) 14:01:37
>>500 いや、たがらね、#include とか 関数とかグローバル変数の宣言とか #define とか、
その辺りを解釈しないで無視するパーサーを作りたかったんですよ。
解釈するパーサーは以前 Parsec で作ったんですけど、
無視するパーサーというのはどうやって作るのかなと。
(頭が硬いのか、うまく作れない)
一応、無視する仕組みは Parsec 以外のものを使って実現はできました。
私に対するレスではなく一般論でしたらすいません。
>>501 struct に遭遇するまでは全てのトークンを空白と同じとみなせばいいだけだと思うんだけど、そんなにめんどい話かな
>>501 こんな感じ↓で構造体作るときはマクロを多用するもんだと思ってたよ
#include <stdio.h>
#define coodinate( suf, type ) typedef struct { type x; type y; } coodinate##suf
coodinate ( S, short );
coodinate ( I, int );
coodinate ( L, long );
coodinate ( F, float );
coodinate ( D, double );
int main(void)
{
coodinateI p = {1, 2};
coodinateD q = {0.0, 1.0};
printf("x=%d, y=%d\n", p.x, p.y);
printf("x=%f, y=%f\n", q.x, q.y);
return 0;
}
504 :
489 :2010/12/26(日) 15:03:11
>>502 それは
T := <改行空白含めて struct 以外の任意の文字列> "struct" <struct 本体>
という構文規則を表現するパーサーなのでしょうか。
それとも、"struct" 以外の "#define" や "void" などのキーワードもとりあえず認識し、
認識した結果として、空白と同じように何もしないというパーサーなのでしょうか。
>>489 どの程度詳しいパースをやるかはお前が決めることだろ
Cに完全準拠したパースをやりたいなら、完全なCパーサ(language-cでも自作でも)を使って
コード全体を解析した上でstruct以外を捨てるしかない
とりあえず動けばいいというならregexでも何でも使えばいい
その中間も当然あり得る
506 :
489 :2010/12/26(日) 15:33:58
>>505 > コード全体を解析した上でstruct以外を捨てるしかない
「解析しない」というのを Parsec で表現可能なのか、
それとも解析した上で捨てるしか Parsec では方法がないのか、
どちらかを聞きたかったんです。
言葉足らずで苛つかせてしまって申し訳ありませんでした。
> コード全体を解析した上でstruct以外を捨てるしかない
わかりました。
文脈から完全に切り離して解釈することは出来んからな。 単純なところを言えば、 struct が現れたところから解釈を始めるだけだと、コメント中や文字列中にあるものにもマッチしてしまう。 厳密にしようとすれば当然、完全な C パーサが必要。
gcc -E でマクロ展開を出力したモノを解析対象にすれば #define とかの解析は必要なくなる
>>507 Parsecで // 〜行末 と /* 〜 */ を以外を抽出すればいいだけじゃ…
>>509 「単純なところ」と書いたのはわかりやすいから。
もちろん、簡単に解決できるところではあるけど、
例外ケースを全部洗い出すと C パーサになるよ。
#if 0 ここをこめんととして使うなんてことはざらですよ #endif
Haskell入門者です。 Haskellレベルで(IOでない)状態を扱うようなコードを書くときは積極的にStateモナドを 使うべきでしょうか。それとも引数をループで回すだけでよいでしょうか? Stateモナドの使い方がパッと見ただけでは良く分からなかったので...。
万能の解はない。 状況による。
>>513 分かる方でやるべき。
後から修正が頻発するようなプログラミングをしてる場合にStateを使うべき。
ぱっと見でStateモナドが分かるならStateモナドを使えばいい。
516 :
513 :2010/12/28(火) 02:16:22
>>514 やはり使い分けですね。ありがとうございます。
>>515 > 後から修正が頻発するようなプログラミングをしてる場合にStateを使うべき。
おお、なんかリファクタリングっぽい。参考になります。
え?
え?
んっ…
ぴゅっ
…ふぅ
そういうネタしかないのはプログラマーとして考え物だな
お前だってhogeとかhageとか変数名につけるだろ? そういうことだ
諸君、お勧めのパッケージは?
525 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/29(水) 11:39:42
まだやってんの?グズどもは さっさとスレ閉じて死んじまえよ イワブキちゃん???
526 :
Perl忍者 ◆M5ZWRnXOj6 :2010/12/29(水) 11:40:50
モナドモナド言いまくって逃げ惑うイワブキをつかんで 壁にガンガンたたきつられたら haskellやめそう(笑)
wikipediaのラムダ計算のページ見てたら、ふと思い立ったので funca x y = x * y funcb a b = a * b main = print (funca == funcb) これやってみたらどうなるんだろうと思いつつ試してみたら普通に No instance for (Eq (a -> a -> a)) って怒られてしまったんですが、 もしEqのインスタンスであるとしたら一応同じということが言えるんですよね?
インスタンスにするときにメソッド == を然るべく定義すれば真にすることは可能であるが、そもそも「同じ」とは何であるかという話になるので初心者はそんなこと考えない方がいい。
>>529 どうもです
そこらへんはあんまり深く追わないことにします。
本末転倒だ。 同じという事が言えるように Eq のインスタンスを作れば、True となる。
えー?そこは、 同じとは何であるかという話をしようよ 考えない方がいい、なんてよく言えたな
>>531 例えばEqで「同じとは何か」を定義するときに
・ラムダ式の計算結果が同じになるか
と
・式の変数名まで同じであるか
のどちらを見るか次第では、TrueになるかFalseになるか変わる、という話になるんですかね
Eqの定義しだい
twitterのボットのリツイートがこわい
>>528 いちおう、次の定義は動く。
{-# OPTIONS_GHC -XFlexibleInstances #-}
module Main where
import Data.Int
instance (Enum a, Bounded a, Eq a) => Eq (a -> a -> a) where
f == g = all (\(x, y) -> f x y == g x y) [(x, y) | x <- l, y <- l]
where l = [minBound..maxBound]
f1, f2, f3 :: Int8 -> Int8 -> Int8
f1 x y = x * y
f2 x y = x * y
f3 x y = x + y
main = do
print $ f1 == f2
print $ f1 == f3
print $ f2 == f3
でも、この Eq の定義が優れたものかどうかは、オレは知らない。
このスレマジで人すくねーよな。 前に釣りリンクここに書いてクリックした人数をカウントしたらたった23人だったよ
23人もいることに驚き
ソフトウェアはコピーできるから、人数は関係ない それがソフトウェアの利点
俺らたった23人しかいないなら勉強会ひらこうぜ
いつも書いてるのは俺含めて3人ぐらいかなと思う
このスレ開いてるやつ全員が釣りリンク踏むと思ってるとかゆとりか
点呼とるか
ID出ないスレで点呼って見たことないわ
つ 節穴
初心者なので普段の会話についていけなくてほとんどレスしてませんが 一応、新レスある度に見てます
レスの内容よりスレの状態が気になるアホは まあ再帰定義なわけだが
Perl忍者も23人の内の一人か?
Perlすら出来ないと告白したPerl忍者は、そもそもマですらない
おしりがかゆい
>>549 できないのになんでそのコテ名乗ってんだよ
一通り Haskell の考え方や使い方は分った(ツッコミゆるさん)。 で、小粒だがちゃんとしたアプリを作り上げてみたいんだが、 何かネタはないかね?
unix の man cat を読んで全く同じ仕様のものをつくってみそ
>>553 ごめん
Windows の GUI アプリで何かネタ頼む
>>555 なるほど、ちょうどいいかも
ちょっと作ってみるわ
ありがと
なぜか遅延評価されて消えないぷよぷよ
558 :
Perl忍者 ◆M5ZWRnXOj6 :2011/01/04(火) 00:16:37
(笑)
Perl忍者ってHaskellわからない&勉強する気が無いのになんでこのスレにいんの?
FRP が最初に提唱された論文ってこれ? Functional Reactive Animation それとも、FRP というのは以前から提唱されてて、 Haskell における FRP を意味論の点からしっかり形にしたのがこれなの?
解決策を提唱する以前に、問題提起をしっかり形にしてほしい。
アブストラクトナンセンスな問題解決の話
564 :
Perl忍者 ◆M5ZWRnXOj6 :2011/01/04(火) 17:48:16
キキ
Fran のソースコードどこかに落ちてない? 本家は reactive に継承されたからもう公開しないよって言ってる
566 :
Perl忍者 ◆M5ZWRnXOj6 :2011/01/05(水) 21:23:41
あっそっすか
Reactiveとか触ってる人いる?(´・ω・`)
>>567 使ってるよ。
活用しているとは言えないけどね。
まだ、いろいろ実験して調べてるところ。
仕組みがいまいち分らん
569 :
Perl忍者 ◆M5ZWRnXOj6 :2011/01/07(金) 20:05:51
俺って知的好奇心がすごいんだぜアピールいいから^^;
全く理解出来ないのにこのスレに常駐しているPerl忍者さんの知的好奇心も なかなかですね
571 :
デフォルトの名無しさん :2011/01/10(月) 11:31:18
初心者のしつもんなんですが なぜGHCをインストールするには MINGWをインストールする必要があるんですか?
>>571 え? Haskell Platform を使えば、MinGWがどうとか考える必要はなくない?
C:\Program Files\Haskell Platform\2010.2.0.0\mingw 以下に入っているような、コンパイラとだかリンカだとかを使うんだろう。
少なくとも、GHCの開発者がGHC専用のDLL用リンカを開発しているとか考えにくい。
なるへそ STOPの意味がやっと分かった。 ではMINGWをインストールしてhaskell Platformの代わりにしよう。
>>573 悪いことは言わん、初心者なら素直に Haskell Platform を入れとけ。
GHC 以外にも Cabal や hsc2hs などのツールもまとめてインストールされる。
入門書とか Real World Haskell とか解説サイトなどは、
そういうツールが既に入ってることが前提で説明されることが多い。
>>575 よく分からないけど、それ、画面のキャプチャと音楽を動画編集ソフトでミックスしているだけなんじゃないの?
>>575 Emacs のバッファ内に書かれた Haskell のソースコードをコンパイルして、
あるいはインタプリタで実行する Emacs Lisp を書けばいいだけだと思うが。
>>576-577 レスありがとう
なんにせよ、GHCiには音を鳴らす機能はなくて、他のソフトなりが必要ってことですかね
580 :
576 :2011/01/10(月) 19:13:34
ごめん。オレが勘違いしていた。 これ、コーディング中(あるいはコーディング直後自動的に)そのコードを実行しているみたいね。 すでに言われていることだけど、flymakeみたいなEmacs LISPを使っているんだと思う。 おわびにちょっと調べてみる。
581 :
576 :2011/01/11(火) 02:14:31
ちょっと試してみたので、報告するぜ。
重いし、もっとうまいやり方があると思うけど、いちようYouTubeのやつに似たことは出来るようになった。
下のやり方でためすなら、けっこう危険なEmacs LISPを使っているので、.emacs ファイルを事前にコピーしておいてください。
(1) まず、HaskoreはMIDIを演奏するとき、外部コマンドに丸投げの模様。
ttp://hackage.haskell.org/packages/archive/haskore/0.1.0.4/doc/html/src/Haskore-Interface-MIDI-Render.html > playWin95 = play "mplayer" []
> playWinNT = play "mplay32" []
> playLinux = play "playmidi" ["-rf"]
> playAlsa = play "pmidi" ["-p 128:0"]
> playTimidity = play "timidity" ["-B8,9"]
> playTimidityJack = play "timidity" ["-Oj"]
外部コマンドに丸投げだから、timidityとかpmidiとかコマンドラインMIDIプレイヤーをインストールすれば、演奏できるようになる。
GHCiからでもO.K.
UbuntuだとTimidityパッケージかpmidiパッケージをインストールすればそのまま使える。
582 :
576 :2011/01/11(火) 09:27:05
なんか、サーバーエラーで書き込めんかった。 (2) .emacs に次のように書き込む。 (defun auto-run-haskell () (let* ((app "auto-run-haskell") (buf (current-buffer)) (_ (save-buffer buf)) (file (buffer-file-name buf)) (tmp (make-temp-file file)) (cmd1 (concat "ghc -o " tmp " --make -x hs " file " > /dev/null 2>&1; echo -n $?")) (cmd2 (concat "ghc -e Main.main -x hs " file)) (ret (shell-command-to-string cmd1)) (_ (when (file-exists-p tmp) (delete-file tmp)))) (when (equal "0" ret) (when (get-process app) (delete-process app)) (start-process-shell-command app nil cmd2)))) ;; つづく
583 :
576 :2011/01/11(火) 09:29:58
(defun auto-run-haskell-on-change (beg end len) (let* ((mode mode-name) (buf (current-buffer)) (file (buffer-file-name buf))) (when (and (equal mode "Auto Run Haskell") file (string-match "\\.ahs\\'" file)) (auto-run-haskell)))) (define-derived-mode auto-run-haskell-mode haskell-mode "Auto Run Haskell" "An experimental major mode" (add-hook 'after-change-functions 'auto-run-haskell-on-change)) (add-to-list 'auto-mode-alist '("\\.ahs\\'". auto-run-haskell-mode)) これで .ahs という拡張子で .hs のように編集すれば、編集ごとにコンパイルチェックをかけ、それが通れば実行される。
584 :
575 :2011/01/11(火) 12:10:13
>>576 さん、どうもありがとうございましたm(__)m
なんとかがんばってみます
FRPを使ってる人教えてたもれ・・・ ・BehaviorとEventの相互変換ができるとあるんだけど(Flapjax)実装的にはBehaviorにChangedイベントのようなものがあってそれを受けて改めてイベントとして変わったことを発行するの? ・Behaviorってモナドなの?(モナドもよくわかってない) ・Behaviorは引数(時間など。なくても可)をもってPullして引っ張ってくる値、EventはPushされるものって理解だけどあってる? C#やってF#で関数型学んだ奴なのでいろいろ間違ってそうなんだか聞けるのここぐらいだったので頼む・・・
Haskell による FRP ではなく、FRP 全般の事を聞いてるのですか?
Flapjax は JavaScript ですよね。
Flapjax の実装はよく知らないので一つ目の質問には答えられないです。
> Behaviorってモナドなの?
実装に依ります。
例えば Haskell 用 FRP ライブラリ Reactivce では、モナドとしては実装されていません。
ただし、元になった論文には「意味的にはモナドだが、実際にはモナドとしては実装しなかった」
という言い方をしていますね(Event はモナドとして実装するのが便利とも言ってます)。
ただ、私自身は Behavior を陽に扱った FRP ライブラリを他に見たことがないので、
Behavior をモナドとして実装しているのは知らないですね。
> Behaviorは引数(時間など。なくても可)をもって・・・
これも実装に依ります。
というのも、そもそも Behavior や Event などは単なる概念なので、
その概念を表現・実現する方法は色々あります。
「概念的には」 Behavior は時間からある値への関数です(時間 -> 値)。
一方 Event は時間とある値のペアのリストです([(時間, 値)])。
Behavior をプッシュする実装もあれば、Event をプルするじっそうもあり得ます。
次の記事と論文がおすすめです。
・
http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming FRP って何? という質問と実装に関する創始者 Conal Elliott(ステキなじーさん)の返答。
67番のレス、今ならページの初めの方にあります。
・
http://conal.net/papers/icfp97/ 同氏と Paul Hudak 共著の論文「Functional Reactive Animation」
ちゃんと理論を提示した恐らく最初の FRP。
>586
>Haskell による FRP ではなく、FRP 全般の事を聞いてるのですか?
です。目的としてはF#でのFRPに近いものの実装なんですが。
そういう意味ではHaskellだとこんなにナイスに出来るよというのでも参考になります。
ざっくりとしてしか見てないんですが、FlapjaxではBehaviorはEventを継承したようなものでEventでかつ、その時の値(時間を引数とする値を返す関数である場合を含む)を持つもののようです。
ReactiveではBehaviorの値が変わったときに自動的に別のものに更新が伝搬したりするんでしょうか?するとしたらその仕組は?
FlapjaxではEventの延長であるので更新時になにか動作させるののイメージがつかみやすかったんですが。
おすすめのリンクの最初の方は読みました。が、なんつーか抽象的で掴みきれてないです・・・
自分的にはEventでのPushドリブンとBehaviorをPull的にしてそれにliftで汎用的にかければ実装も簡単だし効率的だし十分かなぁと。
が、他ではどんなにエレガントにやってるのかを漁ってるうちにドツボにw
FlapjaxのTutorialは割と具体的でつかみやすかったです。
http://www.flapjax-lang.org/tutorial/ 例であがっているBehaviorである値をそのまま代入してどういうふうに実際の動作に結びついているのが不明なんですが。コンパイラによる?
587 > ReactiveではBehaviorの値が変わったときに自動的に別のものに更新が伝搬したりするんでしょうか? Reactive における Behavior は、プログラマにとってはまさに Time -> a という型の関数に見えるように実装されています。 (引数として「時間」を受け取り、何か適当な型の「値」を返す関数) 時間 t を受け取ったらどんな値 v を返そうかというのをプログラマが定義するのですが、 Reactive の Behavior 型の値にはこれ以上の役割・機能はありません。 伝搬の意味が今ひとつ掴みかねてますが、 刻々と時間が経過してある behavior 型の値 v が変化しているとき、 ある関数 f を v に適用するようにプログラムを組んでいれば、 結局のところ関数 f は時間によって変化する値を返すようになりますね。 こうやって「時間による変化を伝える」ことは当然できますし、 プログラマが明示的にそのようにプログラムしないと伝わりません。 伝搬というのはこういう意味の事でよかったですか? Flapjax の Tutorial は今ざっと読んでますので、 Reactive の behavior との違いがあるのか、などは後ほどレスします。
589 :
Perl忍者 ◆M5ZWRnXOj6 :2011/01/11(火) 22:52:36
ここに乗せてあるやつ全部コピペっていってください
>>587 今 Flapjax の Tutorial をざっと読みましたが、
Behavior と Event の概念は Reactive のそれと全く同じ、
つまり FRP 提唱者が最初に提唱したものと同じですね。
> FlapjaxではBehaviorはEventを継承したようなものでEventでかつ、その時の値(時間を引数とする値を返す関数である場合を含む)を持つもののようです。
私はそのような感じを受けなかったのですが、
チュートリアルのどの辺りからそのように感じたのでしょうか?
Flapjax においても、Behavior と Event は
一方が他方を包含したり継承したりするようなものではなく、
全く別のものではないでしょうか。
Behavior は連続時間上の振る舞いを表す、
方や Event は離散時間上の出来事を離散ストリームで表す。
もしかして、Flapjax ライブラリ自体の実装の話でしょうか?
>588,590
>伝搬の意味が今ひとつ掴みかねてますが、
イベントと同様に更新時にそれを参照しているものに何かの手段で伝わるかどうかという意味です。
アニメーションのように繰り返し評価されるため、更新されたことによる関連する値の再評価のタイミングなどを考えないものはいいと思いますが、表計算のようにグラフ的に更新が伝搬されるものが必要なモデルもあるのかと。
>Flapjax においても、Behavior と Event は
>一方が他方を包含したり継承したりするようなものではなく、
>全く別のものではないでしょうか。
Tutorialではないんですが、こちらのリンクの3.2の最後の方に
"Derived Behaviors A behavior in Flapjax is an extension
of event streams.
A behavior node maintains its current value, in addition to sources, sinks, and an update function"
などとあります。
まだ途中までしか読んでないんですが、このへん見てReactiveとは実装上は若干違うのかなと。
http://www.cs.brown.edu/~arjun/public/flapjax.pdf
>>591 > アニメーションのように繰り返し評価されるため、更新されたことによる関連する値の再評価のタイミングなどを考えないものはいいと思いますが、表計算のようにグラフ的に更新が伝搬されるものが必要なモデルもあるのかと。
どうも伝搬の意味が分らない思ったら、私の方が遅延評価で考えていました。
Haskell は基本的に遅延評価なので、必要になるまで評価されません。
たとえば表計算でセルBがセルAを使って計算されているとします。
セルBの値が Event や Behavior を使ってセルAの変化に対応していたとしても、
セルBを再描画するなどの処理によってセルBの値が必要にならない限り、
セルBは自身が持つ Event や Behavior を評価しないのが基本です。
イメージとしては、Event や Behavior の発火元から情報が伝搬するのではなく、
セルなどの末端が必要に応じて発火元から情報を「引っ張ってくる」感じです。
芋づる式に。
なので、セルAが変化したタイミングで本来の情報(セルAの値)と一緒に
「セルBを更新してくれ」という情報も伝わらなければ Haskell では機能しません。
その仕組みをライブラリの中に埋め込んでいてプログラマには見せない方法もあります。
Reactive では逆にその仕組みを作るのをプログラマに任せています。
たとえば Event で「セルBを更新する関数」を伝えたり。
まぁそれでは発火元が情報を伝える先を知っていないといけないので、
普通は Reactive に更に1枚ラップを被せてその仕組みを作り、
末端のプログラマには内部のごたごたを隠して Haskell らしくしますね。
ちにみに、アニメーションは Reactive では一定時間間隔で発火する Event を作り、
その Event に「全画面更新をする関数」を乗せて実現するのが一般的です。
(つまり、一定時間間隔で連続時間の Behavior をサンプリングして離散化します)
あー、Haskellだと遅延になるからまた話が変わってくるのか・・・ が、Eventではその更新された値自体は遅延で引っ張ってくるにしても、更新された事自体は正格的に実行はされるんですよね? いずれにしてもReactiveでのBehaviorとEventの扱いがスッキリしました。ありがとうございました。 自分の実装でBehaviorをどんなふうに実装するかちょっと考えてみます。更新があった時点で副作用させたい時もあるだろうからなんかしらのEvent的なBehaviorは作るのかな・・・ ちなみに >例であがっているBehaviorである値をそのまま代入してどういうふうに実際の動作に結びついているのが不明なんですが。コンパイラによる? これはFlapjaxではコンパイラがliftしたものに展開してくれてるそうです。コレも楽そうでいいですね。
>>593 > 更新された事自体は正格的に実行はされるんですよね?
そもそも、更新という概念じゃないんです。
更新という概念自体、命令型言語特有のものなので。
Reaqctive では結局のところ、adaptE という関数が提供されていて、
この関数を Event 型の値に適用すると、時間通りにイベントの内容を評価します。
たとえば e = [ (0.3, print "a"), (1.5, print "b"), ...] というEvent 型の値があったとします。
(正確にはこのように解釈できるモノです。実際はこんなふうに Event 型の値は作れません)
adaptE e とプログラムすれば、実行開始から 0.3 秒後に print "a" が初めて評価され、
1.5 秒後に print "b" が初めて評価され・・・、という感じです。
adaptE 関数の中身はライブラリに隠されていますが、
たぶん C 言語で言う while (true) {...} みたいな無限ループを作り、
現在時刻を計測しては Event を調べるというような泥臭いことをしていると思います。
(この辺りの実装テクニックの一部が先に紹介した論文で提案されています)
一方 Behavior の方は・・・
>>595 に続く
>>594 からの続き
一方 Behavior の方は、たとえば Behavior 型の関数 sinB があったとして、
print sinB なんてやっても意味が無く(そもそも型が合わないのでコンパイル不可)、
Event と組み合わせて使います。
具体的には、e = [(1, ()), (2, ()), (3, ()), ...] のような Event 型の値があったしとして、
e2 = sinB `snapshot_` e のようにプログラムすれば e2 の値は次のような値になります。
e2 = [(1, sinB 1), (2, sinB 2), (3, sinB 3), ...]
つまり 1 秒毎に sinB をその秒数で計算する関数を要素として持つ Event が作られます。
で、これを先ほどのように adaptE e2 とすれば 1 秒毎に Behavior が評価されるわけです。
もちろんアプリ的には計算だけでは無意味なので、print 関数など組み合わせて表示します。
なので、更新ではなく、どちらかというとサンプリングですね。
Behavior や Event の概念自体は全く同じでも、実装方法や、
ライブラリを利用するプログラマの考え方は Flapjax とは違いますね。
>595 イベントもなんですか。 むーなんかそこまでいくと色々と非効率になりそうな・・・ だからEventの実装が時間と値のタプルになってるんですか。 まぁ実装方法はいろいろだろうしそこはあまり問題ではないんですが。 F#などではFlapjax的に実装したほうがよさげっぽいです。色々と。
>>596 > だからEventの実装が時間と値のタプルになってるんですか。
いや、だから「実装」は全然違いますって。
>>594 でも、正確にはこのように解釈できるモノと言いました。
FRP 提唱者が提唱した Event の概念が「時間と値のタプルの無限リスト」であり、
ライブラリ利用者も Event 型の値の意味をそのように解釈できるということ。
reactive の論文(
http://conal.net/papers/push-pull-frp/ )や、
ソースコードを読めば分りますが、実装は「効率的に実行できるように」
けっこう複雑な仕組みになってます。
余計なお世話だとは思いますが、実装より先に、
「実のところ FRP って何?」という部分をしっかり押さえた方が、
結局のところ近道だと思います。
で、私も説明が下手なので、やはり最初に提唱された時の論文を読んだ方が
断然いいと思います。
>>596 言い忘れていました。
数ある FRP の中でも reactive はどちらかと言うと
アニメーションを得意としているような感じです。
と言うのも、作者(FRP 提唱者)が昔から
Functional Reactive Animation に興味を持ち続けているので。
だから、reactive のシステムを GUI システムの構築に利用するには、
その上に一皮ラッパーを被せたり、reactive を改造する必要があります。
reactive の前身である Fran もアニメーション用で、
Fran を GUI に利用した FranTk というライブラリが別の人によって作られましたが、
やはり Fran をそのまま利用する事はできず改造したと論文で述べています。
なので
> F#などではFlapjax的に実装したほうがよさげっぽいです
言語によってはというよりは、活用目的によって実装を考えるべきですね。
>597
すいません、自分は「概念」と「実装」の区別を場所によって明確に区別せず"実装"という言葉を使ってました。
>余計なお世話だとは思いますが、実装より先に、
>「実のところ FRP って何?」という部分をしっかり押さえた方が、
>結局のところ近道だと思います。
ここをしっかり押さえるのが正直難しいです・・・
ここ数日、いろいろ見て、で結局具体的にどういう事ができるの?というのを行ったり来たり。
ひとまずつくろうとしてるものに十分な感じにはつかめた気もしますが、もっと掘り下げると色々とエレガントにできそうな。
こちらもOCamlですがまた少し別の視点から実装してるようです。
http://ambassadortothecomputers.blogspot.com/2010/05/how-froc-works.html >言語によってはというよりは、活用目的によって実装を考えるべきですね。
ですね。ひとまず必要な部分から手をつけていきます。
Android上で動いて欲しい
MINIX上で・・・
Haskellコードならけっこう簡単に Objective-C にトランスレートできるかもしれん
手続き型言語にコンパイルしないと関数型言語は実行できないんじゃないですか? それとも専用のコンピューターがあれば関数型言語のまま実行できたりするんですか? 手続き型言語と関数型言語は同列に並んでるけど、本当は上下関係じゃないですか?
独自用語なら何でも言える
ParsecみたいなLLのパーサだと 左再帰やFirst/First、First/Followのコンフリクトが起きますよね よくRFCとかにABNFが載っているけど、これをそのまま書き下すと 左再帰はchainlがあるとしても First/FirstやFirst/Followのコンフリクトが起きます こういうコンフリクトは手動でBNFを変形して解決されてるのでしょうか? もしそうだとすると、実用レベルではLRパーサのほうがいいのかなとか 思うのですが、いかがでしょうか 今作っているプログラムで、そこでちょっと詰まったもので
うむhappyとalexだな
Parsecの質問です parser = many1 letter `sepBy` delimiter where delimiter = char ',' 上はcharが区切りの場合ですが、 delimiter = string "hoge"ならmany1 letterの部分をどう書けばいいんでしょうか?
>>609 何も変える必要ないよ
many1 letter のままでいい
なぜ何か変えないといけないと思った?
>>610 many1 letter だとhogeにもマッチしてしまうためです
実際、結果もそのようになります
>>611 あぁ、そういう事ね、確かに
以前やったような気がするから、ちょっと思い出してみる
RWHを読んでるのですが、Stateモナドのありがたさがよく分かりません。 乱数以外のもっと簡単なStateの例題があったらおしえてください。
よい例題と言うとちょっと思い浮かばないんだけど 逆に State を使わなかったとしたらと考えてみて。 状態を表す変数を受け渡さないといけないわけ。 その受け渡しを隠してくれるのが State モナド。 State に限らずモナドはそういった暗黙の受け渡しを担っていると言える。 もし今までにオブジェクト指向でのプログラミング経験があれば「カプセル化」が重要だということはよく知っていると思うけど、 モナドは Haskell においてカプセル化を実現するための機構と考えればいいと思う。
>>613 圧縮展開で
スライド辞書をStateモナドで実装したことある
・状態の「受け渡し」を表現してる ・Stateのコンストラクタの引数が関数 ・>>= の右側の引数が Stateを返す関数 この3点が難しくてひっかかる
>>611 昔のソースコードを漁ってやっと思い出した
sepBy は使ってなかった
結局これで一応できる
many (try (manyTill letter $ string "hoge") <|> many1 letter)
かなり不格好になってしまった、もっと洗練された書き方があると思う
また、"hogeABChogeEF" の結果が ["", "ABC", "EF"] となって、
sepBy とは微妙に挙動が違うので注意
「文字列 s の直前まで任意の文字列にマッチするパーサー until」が作れれば、
until s `sepby` string s でできると思う
昔のソースコードには試みた形跡があるけど、面倒になって諦めたみたい
モナドをプログラマーの使い道的に見ると コンティニュエーションの連鎖で次のものにいろいろ渡したり計算の前後でゴニョゴニョ処理を紛れ込ませられるって把握しとけば夜露死?
619 :
609 :2011/01/17(月) 00:52:06
>>617 manyTill letter (try $ string "hoge") <|> ..でいけました
結果はnot . nullでfilterして使うことにします
遅くまでありがとうございました
わかりやすい (a,s) -> (a,s) 汚い a -> s -> (a,s) マジキチ a -> State s a
>>609 >>617 解決できればなんでも良いけど、それ、もしかして字句解析と構文解析を分けるべきところではないだろうか。
>>613 GHCのコンパイラ機能・インタプリタ機能をライブラリとして使うAPIが、独自モナドだけど機能的にはStateモナド(+ IOモナド?)と同じものを使っているよ。
さっき話題になっているParsecも、やはり機能的にはStateモナドの一種。Stateモナドとして実装することもできただろう。
haskellの文字の色が変わるエディターないですか?
>>622 >>633 の他にも Editra や Yi も構文を解析して色を変えられる
構文を解析するほど機能的ではないが、
文の正規表現にマッチした所の色を変える程度でよければ、
(関数のシグネチャを定義する所とか、大文字で始まる識別子とか)
秀丸など他にもたくさんのエディタでできる
625 :
624 :2011/01/17(月) 12:54:40
ghciがreadlineからhaskelineを採用するようになってから 履歴(↑、ctrl-p)の表示に時間が掛かることがたまにある
>>626 うちは最新の Haskell Platform 入れてるけど、
ghci の履歴で待たされたと感じたことは一度もないな
履歴と言ってもせいぜい過去4、5件分さかのぼる程度だが
どのくらい時間掛かるの?
>>627 数十秒
他の作業をしてghciに戻ってくるとよく発生する気がする
スワップアウトしてるのかな
数十秒って冗談だろ、俺の自慰完了よりなげーよ 遅いのは履歴(↑、ctrl-p)の表示だけなの? ロードとか、関数の評価とか、シェルコマンド実行とかはどうなのよ そういうのは気にならんの? 再インストールした方がいいんじゃないかな
>>629 遅いのは履歴だけだよ
それも一つ前の履歴を表示する時だけ
ていうか早漏すぎだろ
他にhaskelineを使ってるプログラムって何があったっけ?
とくに見当たらんな haskeline で何か自作してみればいいんでないか それでも数十秒も待たされるんなら、 そちらの PC と haskeline の相性が悪いんだろ ちなみに、一度 ghci を :q で落としてから立ち上げ直すと、 しばらくは正常なのか? それで実用上問題ないのなら、そういう使い方でも良いと思う 立ち上げ直しても、履歴は消えずに残ってるから
確かに。自作すればいいんだな サンクス
haskelineはキーボードとの相性というオチの可能性があるから怖い
ghciの履歴って、その度にファイルに書きこんでるんでしょうか? だったら、後からコマンド一覧を見てコードの参考にしたいので、そのファイルの場所が知りたいです
3行だけ処理ってのをもっとすっきり書けないでしょうか main=do cs <- getContents threeline <- mapM return (take 3 $ lines cs) mapM_ putStrLn threeline 自分の端末EOFがうまく入らなくて 設定するのもめんどくさくて
threeline <- mapM return (take 3 $ lines cs) は let threeline = take 3 $ lines cs で良いと思う。
ありがとうございます。 3行まとめて処理ではなくて 1行ごとに処理されて前より便利になって嬉しいんですが これは何故なんでしょうか
main = interact (unlines.id.(take 3).lines) % main.ext < file.txt
interactは便利ですね、ありがとうございます。 --run :: (CharParser () String) -> String -> String myrepl f n = interact (unlines . (map f) . (take n) . lines) main = myrepl (run p) 3
>>638 getContentsは遅延IOだから所望する分だけ入力してくれるけど、mapMをかますことで一枚岩のIOとなるため。
遅延IOを操りたければ、System.IO.UnsafeのunsafeInterleaveIOを調べるべし
以前ブラックボックスだったところが少し理解できました myrepl f n = g >>= putStr . (unlines . (map f) . (take n) . lines) where g=unsafeInterleaveIO $ liftM2 (:) getChar g main = myrepl id 3
Parsecの質問です(2系) εを含む文法に対するパーサ(optionalやmany等)を<|>でつなぐ際、 εを含む文法のパースは必ず成功するため、 <|>でつながれている別のパーサにマッチしてくれません。 tryも機能しないのですが、どうやってバックトラックさせれば良いのでしょうか? 例えば(["+"] | "-") ...をパースする際、次のパーサだと ((option "" (string "+")) <|> string "-") >> string "1" +1と1はパース出来ますが-1がパース出来ません optionの前とstring "+"の前にtryを両方/片方だけはさむ3パターンも同様の結果です LALR(1)のbisonではうまくいきました 同じくLL系のANTLRは構文木ごとにTreeWalkerなるものを 作らないといけないっぽくてきちんと確認するのはやめましたが antlrworksでは-を通る図が描かれるので多分動きます parser : ('+'? | '-') ('0' .. '9');
>>643 根本的な解決になってるか知らんが、
<|> の右辺と左辺を逆にしたらいかんの?
(string "-" <|> (option "" (string "+"))) >> string "1"
つまり、εを含む文法を OR の一番最後で判定する
>>644 わかる範囲では、基本的に指摘して頂いたような感じで解決しているのですが、
ただ、複数のεを含む非終端記号が<|>でつながれていたり、
修正がその非終端記号だけでは済まなさそうなものも多くて
手作業で修正するのは絶望的です(正しく動くか検証出来る気がしないです)
出来れば元のBNFは修正せずに何とかならないでしょうか
>>645 他の構文解析器のことは知らんが、Parsec の run 系関数は、
入力されたパーサーが文法的にεを含んでいるかどうかを全く把握しない
(そもそも、各パーサーがεを含んでいる事を外部に知らせる術がない)
> 出来れば元のBNFは修正せずに何とかならないでしょうか
残念だが、現時点のバージョンの Parsec では何ともならんと思うぞ
> 手作業で修正するのは絶望的です
これは、Parsec で作った自分のパーサーを見て、
これは εを含んでいる、これは含んでいないと見分ける方法、
つまりアルゴリズムは持っているが、手作業では面倒だという意味か?
もしそのような意味であればラッキーだ
そのパーサーのプログラム文を解析し、
<|> の各項を適切な順に並べて出力するパーサーを作ればいい
その方法がない、あるいはそれも面倒なら、絶望的だな
後者ですね、残念 A = Be | Ce | De | F Be = B* Ce = C? De = D >> string "" --この種もε? これを書き換えるとすると A = B' | C | D | e B' = B+ 最も外側にある<|>までさかのぼってこの種の変換をする 再帰関数を書くことでうまくいくかもしれないけど 正しく動くのか検証出来そうにないです Maybe C -> C みたいにパース結果の型も変わるだろうし 色々と調べてみて RFCにあるようなBNFをそのまま記述するだけで何とかなる、 みたいな夢のパーサジェネレータはないのかなと思いました そういうのを実現出来るものがあるとすれば GLRみたいなアルゴリズムを実装するしかないんでしょうね そうすると実用的な速度では動かないから 実用レベルでは、もうちょっと細かいハックが色々と要るってことなのかな
>>674 Parsec や Haskell の勉強ではなく、純粋にある文を構文解析した結果を
Haskell で処理するのが目的なら、うまくいくという bison を
中間処理モジュールとして使えばいいのでは?
あるいは、LR 文法を解析する Haskell コードを生成する Happy を使うとか
これも yacc や bison などと同くコンパイラ コンパイラのひとつ
GHC で使われている実績もあって、コンビネータの組み合わせで表現する
Parsec などのパーサーより速いそうだ
ちらっと見たところ、ソースも yacc などとほとんど同じだ
(使ったこと無いから、あとは自分で調べてくれ)
はぁ・・・
またレス番間違えた
>>648 は
>>647 宛だ、すまん
今 Happy のユーザーガイドをざっと眺めてたら、
GLR パーサーが作れるみたいだな
(つまり、GLR アルゴリズムを使って構文解析する Haskell コードが生成される)
>>649 さん色々とありがとうございます。
GLRが解析出来るっていいですね
parsecを知るとbisonはちょっと使う気になれないので
happy調べてみます
マスコットがわりと癒し系
このぐらいの可愛さだと安心。
>>439 ・・
sepByのセパレーターやmanyTillの〜までのパーサは同じような用途なのに どうしてmanyTillの方だけtry必須なんですか?
すみません。 Data.IORef って、値の再代入をしてるんでしょうか? それとも、内部では再代入をしないトリッキーな方法で、再代入の機能を実現しているのでしょうか?
>>651 べつに必須というわけじゃない
必須なんてライブラリ ドキュメントのどこにも書いてないだろ?
次の2つのパーサーのパース結果を色んな文字列で比べてみればいい
manyTill (string "abc") (string "abd")
manyTill (string "abc") (try $ string "abd")
ちなみに、Parsec のソースの Combinator.hs を見てみれば、
この場合になんで try がいるのかすぐに分る
意外にシンプルに書かれたソースなんで、
ついでに他の関数の中身も見てみるといいよ
ParsecつかうのとANTLRとか使うのどっちが楽?
「楽」の意味が分らん 具体的に聞け
独自の文法作って、それを解析したものに応じた処理をかくとして、デバッグのしやすさを含めた開発生産性。
Parsec の方が、解析と、解析結果を使うのと両方が同じ言語で一体となってて、 プログラムしやすいしデバッグもし易い。 なにより Haskell が使いやすい言語だし。 あくまで、Haskell に慣れ親しんだ者のごく主観的な「楽」です。
658 :
651 :2011/01/20(木) 21:04:14
>>653 色々試してみたけど、try抜きでは有用な使い道は無いと思うんですが
>>658 > try抜きでは有用な使い道は無いと思うんですが
それは分るが、言いたかったのは
「manyTill だから必須なのではない」ということだよ
Aをパースして失敗したらBをパースする
という仕組みの「全ての」パーサーにおいて、
Aを途中までパースしかけたけど無かったことにしたい場合に、
try が必要になるだけのこと
manyTill がその仕組みになっていることは、
使い方やドキュメントから何となく分ると思うが、
ソースを見た方がよりはっきりするからソースの読解を奨めてる
関数の中で try を使っているかもしれないし、
プログラマに明示的に try を使ってもらうタイプのものかもしれない
そういう意味でも、やはりソースを見た方がいい
なぜ manyTill では try が要るのと考えていると、
他の提供パーサー、自作パーサーで同じような問題にぶつかり、
解決できなくてまた同じ質問することになりかねない
OpenGLでビューアを作ってコンパイルしたらサイズが7MBになったんですけど、こんなにexeファイルって大きくなるんでしょうか? C言語で作った同様のソフトは300KBでした。
662 :
デフォルトの名無しさん :2011/01/22(土) 02:18:04
ソースコードを渡さずに、モジュールを配る方法を知りたいです モジュールをオブジェクトファイルみたいに中身がテキストじゃないファイルに変換した後、モジュールのソースファイルを一切参照せずに、そのモジュールをimportしてコンパイルまでする方法ってないですかね
↑ちなみにソースが汚いので見せたくないからです
>>662 .oファイルと.hiファイルを配布すればできるんじゃね?
オレはためしたことないけど。
Module.hs ... モジュールのソース test.hs ... Module.hsをimportするファイル % ghc -c Module.hs Module.hs と Module.o ができるので、これを test.hs と同じディレクトリに置く(Module.hsは削除) % ghc -o test test.hs Module.o -package p1 -package p2 -package p3 p1, p2, p3 は test.hs から import するGHCに附属する他のモジュール でできた
ghc -c でできるのは Module.hi と Module.o だ…
.oと.hiファイルだけを配布する場合、OSとアーキテクチャに加えて GHCのバージョンが配布元と一致してないと使えないのでかなり不親切 READMEに「ソースは読まないで下さい。読んだら呪う」とか書いとくのが良いと思う
>>667 じゃ、静的リンクではどうだろう?
Wiinows環境で静的リンクってできたかよく知らんし、GPLやLGPLのライブラリと静的リンクして、オブジェクトだけ配布するのはライセンス違反だけどね。
ソースは読んでほしくないけど、「こんなのできた」って自慢したい いったいどうすれば…
ソースをモザイクを掛けて動画でみせつける
これがホントの難読化
C言語は納品するときに、ソフトで空白や改行やコメントを抜いたり入れたりして、わざとスパゲッティコードにしてる Haskellだとそれができないから困る
コメント欄に、グロAA
AAでグロってなかなか難しいな
>>672 { ; } でインデント依存をなくせばいいじゃない
>>675 空白タブと{ ; }は単純に置換できないから、自動化は頭使うと思う
>>672 空白や改行を増やしたり減らしたりしても、自動整形ソフトがあるから意味ないような。
高階関数を使いまくって難読化できないかな ソースは凄く見難くなるけど、Stream Fusion などの仕組みで コンパイル後は結局普通のソースと同じ働きをするコードを吐くみたいな
GHCなら構文糖を全部展開した中間コード生成できた気がする。 それ使えば難読化も可能じゃないかな
ghc -ddump-ds するべし
Haskellはもっとモナドの操作を意識した構文を採用してほしい ifM then else、caseM .. ofみたいな構文を入れてくれれば caseの前に<-で一行増えるなんて悩みが無くなるのに ifM :: (Monad m) => m Bool -> m a -> m a -> m a だと今度は括弧がうざい
1行増えることがどれほどあなたを悩ませてるのか、想像できん
最近halpをemacsに導入してみたが悪くない。
https://github.com/darius/halp/ python2.xが要るけど、<M>-iでコメント行の式を評価してくれる。
--- 1+2
--- putStrLn "Hello"
とか書いといて<M>-iで評価すると
--- 1+2
-- | 3
--- putStrLn "Hello"
-- | hello
とかしてくれるし、ghciの機能である:tとか:iも打てる。エラーメッセージが出ないのだけが難点か。
モナー化
mf criteria operator list = filter criteria (map operator list)
これをポイントフリー化しろっていう練習問題(wikipedia)に挑んだんですが
ttp://en.wikipedia.org/wiki/Tacit_programming#cite_note-1 多分こう変形出来ると思うんですが
f (g x y) ≡ (f .) (g x) y
一般にこれって言えるんでしょうか?
f (g a1 a2 ... an-1 an) ≡ (f .) (g a1 a2 ... an-1) a
(3つ連続してる点は関数合成ではなくa3 a4 と続いていくという意味)
自己レス。間違ってました
>>681 計算の組み立てをするという問題について、モナドは解のひとつだけど、最適解ではない
という話を聞いた
それが本当なら、モナド特化の構文はもうちょっと様子を見た方がいいと思う
Arrow とかが人気でてるって聞いたけど
だれかモナドとArrowを分かりやすく説明してくれ・・・
>>690 Monadは、説明を聞くよりもStateモナドとListモナドを自分で再実装していじくりまわすのがお勧め。
MonadよりComonadの解説が聞きたい
余モナドって使えるもの?
Arrowは.NETのRx的な感じなのかなー。数学的な位置づけとかは良く解らんが、使い方はわかった。 誰かがRxはモナドなのかとか言ってたがそれにはうまく答えられんがw
>>690 アローの自分の理解
受け取り:関数
返すもの:(関数の引数の型)と(関数の戻り値の型)を入れた箱
アロー同士をくっつけて、関数を色んなやり方で合成出来る
関数A:文字列(テーブル名) -> 数値(主キー)を
関数B:数値(主キー) -> 文字列(名前)
関数C:数値(主キー) -> 性別(名前)
この3つに対応するアローを作って適切な順序で合成すると、
テーブル名を入力して、(文字列,性別)の組を返す関数が作れる
>>696 わざわざアローを使う意義がわからんなぁ
それなら、普通に関数の合成でよくない?
アローによって抽象化された概念が、
関数の合成「以外」にも応用できないと、
抽象化の意味があまりないような気がする
アローによって抽象化された概念とやらが
一体何なのか未だによく分らんが
Arrowって魅力的な実例が少ないんだよな 正確に言うと、MonadにはならないがArrowになる実例 パーサもFRPもXML処理もMonadになることが多そうだし
>>700 > 副作用がある特別な関数を抽象化したのがアローですよね
そうなの?
「計算」という概念を抽象化して圏論の視点で構築したのがアローじゃないの?
モナドも「計算」という視点で捉え直せば Kleisli というアローで一般化できるのだと
アロー自体に副作用の概念は特にないと思ってたのだが
703 :
700 :2011/01/29(土) 20:29:53
>>702 正しくは「抽象化した」でなく「抽象化できる」ですね。
確かにアロー自体には副作用の概念はなく
副作用があろうがなかろうがアローにできます。
実際にアローを使うのは普通の関数では書けない時だから
その時はアロー合成を関数合成に置き換えられないという話です。
副作用の話はとりあえず置いておいて 確認なんだけど、結局同じ引数に適用したら同じ値に還元されるという意味において、 モナドは 100% アローで表現可能だし、アローは 100% モナドで表現可能だよな? もしかして違うか? 違ってたら完全に私の認識が間違ってるっぽいから、 もう一度ちゃんと勉強し直したい
>>704 > アローは 100% モナドで表現可能だよな?
違う。少なくとも、HaskellのControl.ArrowとContorol.Monadはそうではないし、
数学的にも、よく分からんが、たぶんデカルト圏かならずしもモナドならず、ということだと思う。
Arrowインスタンスにappメソッドが定義されていればそれはモナドと等価であるけど、定義されていない、定義できないのであればモナドではない。
appメソッドは次のように宣言されている:
class Arrow a => ArrowApply a whereSource
app :: a (a b c, b) c
Arrow記法で書くと
x <- aArrow -< aValue
と
x <- app -< (aArrow, aValue)
が同じ意味であるようなappを定義できるか、ということになる。
706 :
705 :2011/01/30(日) 01:25:17
オレがこの間まで試していたものが、実際にこのappを定義できないArrowだった。 data MyArrow a b = MyArrow { runMyArrow :: a -> (b, MyArrow a b) } stepper :: b -> (b -> a -> b) -> MyArrow a b stepper init f = MyArrow $ \a -> (f init a, stepper (f init a) f) このMyArrow型はメモリのある電子回路のようなものをイメージしており、 例えば、 st = stepper 0 (+) (x, st') = runMyArrow st 10 -- x = 10 (y, st'') = runMyArrow st' 5 -- y = 15 (z, st''') = runMyArrow st'' (-20) -- z = -5 というように使う。 これをArrow、ArrowChoice、ArrowLoopのインスタンスにすることはできたのだが、ArrowApplyのインスタンスにすることは出来なかった。 考えみれば、 y <- stepper 0 (+) -< x と st <- arr (const $ stepper 0 (+)) -< () y <- app -< (st, x) が同じ意味になるように定義することはできない。少なくともオレがモデル化しようとしていた回路の世界では。 上の例だと、その回路には最初からカウントアップする回路部品が含まれており、回路全体が繰り返し計算されることによってカウントアップされていく。 しかし、下の例だと、回路全体を計算するたびに新たにカウントアップ部品が生成されてしまうので、意味がない。 手前味噌かつ簡潔すぎて分かりにくいと思うが、まぁ、モナドに出来ない具体例は意外と簡単に見つかるよ、という話。
デカルト圏とカルテシアン閉圏って同じなの?
708 :
705 :2011/01/30(日) 02:01:13
ごめん。 > たぶんデカルト圏かならずしもモナドならず、ということだと思う。 というのは、分かっていないのにディレッタンティズムに駆られて余計なことを書いた。 これは取り消す。
あかん、本質的に Arrow とは何かを学び直さないと 論文漁ってくる
ここまでの流れ、「Monad/Arrowがよく分からねえ!!」という人は
自分だけじゃないらしいので、少し安心した。
自分の中では「結合子(combinator)とMonad/Arrowとの違い」が分かっていない。
たとえば
>>701 は、Monadの例としてパーサ/FRP/XML処理を挙げているけど、少なくとも
・パーサ(形式言語の字句解析/構文解析)や
・XML処理(木構造をベースとした言語のvalidation/transfom/encode)は、
Monad/Arrowみたいな難しい概念を導入しなくてもcombinatorだけで書けるし、
その原理を説明できる。(FRPや副作用の話は知らない&分からない....)
実際Haskellでなくても、Monad登場以前の言語であるMiranda/Goferでもcombinatorで書けるし、
MLのようなinfix定義の可能な作用順評価(=非遅延評価)な関数型言語ならばcombinatorで書ける。
それどころかJavaやRubyのような非関数型言語でも表現力は劣るけどcombinatorで書ける。
(
http://jparsec.codehaus.org/ を参照)
歴史を振り返れば、関数型言語への(ラムダ計算モデルにおける)combinatorという概念の導入は
BackusのFP(1978年)が最初の挑戦であり、その後にMLの型システム(1976-83年)によって
型安全性が保証され、さらにMiranda(1985年)によって正規順評価言語にも適用が拡大する。
そして最終的にこれら成果の結集としてHaskellが誕生し、Monad/Arrowへ発展していく。
自分の中では、おそらく
>>702 の言い方をマネすると
「combinatorを圏論の視点で再構築したのがMonad/Arrowである」
じゃないのかな?と想像してる。ただ、自分にはそもそもの圏論(category)が大きな壁に....。
というか、分かったつもりでいた初等代数系(群/環/体/束)に関する自分の知識(自信)が崩れ去り、
一から再勉強し直すことに...orz。やっぱりMonad/Arrowは難しいと思う。
というかざっくり言っちゃうと、 モナドは(a -> M b)が結合できるもので、アローは(A a b c)が結合できるもの、それにいろいろ理屈を付けただけでしょ。 モナドは結合する単位が(a -> M b)という関数の形に限定されるから、アローより限定的なものしか表現できない。 それでいいんじゃないの?
>>710 その見方は大袈裟すぎ
パーサコンビネータのライブラリを良く見てみると、モナドとしての要件「も」満たしていることが分かった
→せっかくだからMonadのインスタンスにしようぜ
→do記法やらmapM_やらがタダで使えてハッピー
というだけ
別にコンビネータライブラリを書くときにMonadやArrowインスタンスを与えなきゃならんという決まりはないし、
実際Text.PrettyPrint.HughesPJなんかはモナドでもアローでもない
大学でドラムコホモロジーの勉強した(みたいな)んだけど、これ知ってると、Haskellのモナドを簡単に理解できますか?
>>713 勉強したみたいなら、Haskellのモナドを簡単に理解でるか
自分で試してみればいいんじゃね?
>>711 それでいい人もいれば、それではなんか気持ち悪い人もいる、それぞれだ
俺は後者、理屈が分らんと気持ち悪い
理屈というか、「(a -> M b)が結合できるもの」とか
「(A a b c)が結合できるもの」を抽象化できないと気持ち悪い
抽象化できると(抽象化の過程が理解できると)、
たいていは今まで隠れてた本質が見えてくる
その抽象化の道具として今のところ数学が役に立ってるけど、
別のもので綺麗に抽象化できるならそれでもいい
趣味でHaskellプログラミングを楽しんでいる人達にとっては それでいいんだろうし、それはもっともな話だと理解できる。 ただ、
>>715 「「(A a b c)が結合できるもの」を抽象化」、ってのがよくわからない
結合法則の利点がわからないとかそういう事なら
計算の順序を変えられる→計算を楽に出来ること、っていう例を知ればいい
例えば置換行列積の問題とか
ミス、置換行列積じゃなくて連鎖行列積
>715 その辺の抽象化したらこんなナイスなことがあるよというのがわからんのよね・・・ 使う分にはどこぞの説明であった副作用をすべて背後に押し付けて云々で良い気がするけれど。
>>717 (A a b c) や 結合 に含まれた本質のみを抽出することを俺は抽象化と言っていて、
その抽出したものを表現するのに今のところおそらく圏論が役に立つであろうということ
(A a b c) って圏論的にはどういうこと?
結合、あるいは結合できるとは圏論的にはどういうこと?
というのを圏論の言葉で説明できると、圏論で培ってきた法則やテクニックが使える
そうして得られたものはまた Haskell の言葉で表現し直すことができそうだ
一見関係ない様々なものが群論というものに抽象化したことで理解が進んだように、
こちらは論圏で抽象化することで理解が進むのではないかと思われる
きみが「例えば置換行列積の問題とか」と言ったのも、
「(A a b c)が結合できるもの」を抽象化したものを行列の言葉で表現してる
自然に頭の中で普通に抽象化してるんだよ(特に意識してはいないと思うけど)
それ具体化じゃね
「それ」ってどれ?
「これが圏論使ってこんな風に表現できるんなら、圏論のこの概念ってこういうのに応用できるんじゃね?」 ということかい?
>>723 そういうことを期待している
ただ、まだ圏論自体を勉強してる最中だから、
本当に役に立つのかは俺自身は分らない
(役に立つことをまだ経験していない)
最近はデータベースとかで使えるって話題もあるな。 「NoSQL=CoSQL」とか。
幾何学から圏論に入った口だが、数学でならった圏論とはかなり隔たりがあると思うのは気のせいだろうか…
>>711 (A b c)が順次結合できるだけなら、Control.Categoryクラス。
Control.Arrowクラスは、それに加えて、(b -> c)を(A b c)に変換できるarrメソッドと、平行化(?)できる***演算子などが定義されている。
(A b c)が順次結合できるっていうのは、圏論的にはもちろん射の合成に相当するだろう。
arrは、関数を射とする圏から(A b c)を射とする圏への関手に相当するだろう。
>>723 ,724
「これが圏論使ってこんな風に表現できるんなら、圏論のこの概念ってこういうのに応用できるんじゃね?」っていうのはオレには分からないけど、
MonadやArrowのdo記法の存在が既に圏論的な抽象化の産物であって、オレ様Monadやオレ様Arrowもその記法を利用することができるというのは、
小さくはない恩恵だと思う。
>>710 のいうパーサ・コンビネータをモナドにする利点としても、数学的に云々という話ではないかも知れないけど、
Control.Monadのインスタンスにすればdo記法が使える、というのは大きな利点じゃないかな。
do記法なしでParsecを大規模に使うなんて、想像したくない苦行だと思う。
728 :
717 :2011/01/30(日) 15:24:26
>>720 自信ないが結合法則は圏論でも集合論でも意味は同じだと思う
圏論のMonad
T:(a -> b) -> m a -> m b
η:a -> m a
μ:m (m a) -> m a
Haskellのモナド(Kleisi triple)
T:(a -> b) -> m a -> m b
η:a -> m a
*:m a -> (a -> m b) -> m b
Arrow版は知らない
Arrowが役立つ具体例が欲しいな
>>729 Yampa
Grapefruit
などの FRP の実装とか
あとは ACM の Digital Library を漁ると色々出てくる
たとえば、Secure Information Flow にアローを利用する例とか
添え字付のmapってないんでしょうか(ocamのList.mapi) こんな感じでHoogleに入れてみたんですが見つかりません (Integer -> a -> b) -> [a] -> [b] (a -> Integer -> b) -> [a] -> [b]
そういう場合は zipWith を使う f :: Int -> a -> b g :: a -> Int -> b zipWith f [0..] a zipWith g a [0..]
なるほど、こういう時に無限リストが使えるんですね。ありがとうございました
>>726 圏を形式体系の表現として使いたい(個々の射の形が重要)のと
関手を定義する際の枠組みとして使いたい(幾何的対象を如何に代数化するかが重要)のと
焦点が違うんじゃないかな.
つーか、モナド関係なくね? モナド則を自動チェックしてくれるわけじゃないし モナド則破ってても見た目は普通に動いちゃうし
おいハスケルプラットフォーム次期リリース 1月ってなってるのにもう1月終わるぞ
(a, a)の両要素にa -> m bを適用する場合に、お決まりの方法ってありますか?
738 :
737 :2011/01/31(月) 23:45:08
得たいのはm (b, b)です
お決まりの方法というのは、正にそのような働きをする関数が 標準ライブラリに存在するかという意味でしょうか? であれば、残念ながらありません また、実現する方法はクラス m に依るので、 任意のクラス m に対応する仕組みを作る、 ということもできないと思います もしクラス m がモナドであれば、 タプルのそれぞれの要素に関数を適用し、 それぞれモナドを外してタプルにして 再びモナドで包むという、ごく普通の対応になると思います f :: (Monad m) => (a -> m b) -> (a, a) -> m (b, b) f g (x, y) = do x' <- g x y' <- g y return (x', y')
740 :
737 :2011/02/01(火) 00:19:53
>>739 ありがとうございます
どこかで見た気がするんですが、勘違いだったようです。
>>737 定番の方法というのは分からないけど、三つ思いついた。
import Control.Arrow
import Control.Monad
f, g, h :: Monad m => (a -> m b) -> (a, a) -> m (b, b)
f k (a, b) = liftM2 (,) (k a) (k b)
g k = runKleisli $ (Kleisli k) *** (Kleisli k)
h k = uncurry (liftM2 (,)) . (k *** k)
もし、課題が (a -> m b) -> (a, a) -> m (b, b)ではなく、(a -> m b) -> [a] -> m [b]であったなら、mapMがまさにそれ。
mapMのほうが一般性が高いし、とくにタプルにする理由がないのであれば、リストにしてmapMを使えば良いのではないかと思う。
もしa,bがどちらも多相型変数なのであれば a -> m bはかなり特殊な型 ググってみたがforeverとか何に使うんだこれ unsafeCoerce :: a -> b forever :: Monad m => m a -> m b mがリストなら (a,a)->(m b,m b)ならぬ [a] -> [[b],[b]]ときて sequence :: Monad m => [m a] -> m [a]が使えそうな
>>742 forever :: m a -> m b は、IOモナドなどを永遠に繰り返す関数。
引数の型 a は使用しないので何でも良い。
原理的に戻ってこないので、返り値の型 b は何でも良い。
というわけで、そういう方になっている。
unsafeCoerce は黒魔術にして変態技術。気にするな。
>>742 forever は
>>743 が言うように無限ループを引き起こす関数で、
FRP の活用でお世話になった
スレッドを分けて、他方を無限ループにして外部入力をポールする
unsafeCoerce はお世話になったことないな
ghcのパッケージ依存性って厳密すぎやしない? 同じバージョンのパッケージをリビルドするだけでそれに依存するパッケージもリビルドしなきゃならない。 pkg.cabalでバージョン依存を-anyにしてもビルドするとその時のpkg-idに依存するようになっちゃう。
ライブラリのAPIが変わってなくてもGHCから見るとインタフェースが変わり得るからだな パッケージを跨いで積極的な最適化をすることのトレードオフで、 インタフェースファイルの内容が実装に依存することになってしまう
しょうもない質問ですが 短いmainのいい記述法ってありますか ghci、コンパイルエラーの時はimportしてる型の:tや:iが効かないため とりあえずコンパイルだけしたいことが良くあるので 今のところ知ってる中では main = return () これが一番短いです
main 自体書かずに(消すかコメントアウトして)、 インポートだけ書いて ghci でリロードすればいいだけとちゃうか そういう意味ではない?
main=main
>>747 ( ゜Д゜)なん・・だと・・?mainは要らなかったんですね
>>748 ( ゜Д゜)なん・・だと・・?型注釈付けても動きよるです
( ゜Д゜)レス番が・・
>>750 > 型注釈付けても動きよるです
そりゃそうだろ
動かなきゃ再帰なんてできない
main = undefined
Current stable release: 2010.2.0.0 (July 2010) Next release: January 2011 Problems?
>>755 よく分からないけど、どうしてそう思うのか教えてほしい。
Haskell の型クラスとそのインスタンスとなるデータ型の関係を図示しようとする時、 UML のクラス図のクラスとインスタンスの関係と同じように 両者を結んだ線のクラス側に三角形を描くようにするのでしょうか。 それとも、Haskell では一般的な図示の方法は提案されていないのでしょうか。
>>756 あんまりまとまっていないからうまく説明できないけど、
前にスレに貼られていた論文
ttp://hdl.handle.net/10119/908 に、モナドというのは表示的意味論に関係が深いような記述があった。
表示的意味論というのは完備半順序という構造をとるデータ領域の意味を
領域上で連続な型コンストラクタの最小上界であるとする理論だと理解した。
補足的に完備半順序は別に完備束でもよいという記述を見つけたので、
束論を調べてみた。
ttp://ja.wikipedia.org/wiki/%E6%9D%9F%E8%AB%96 そこで、最小上界にあたるjoin(結び)という用語を見つけた。
これはなにかHaskellのControl.Monad.join(モノイドでは積にあたる)に
関係しそうだな、と思っていたところ、圏論の基礎のp189-190に
順序を保存するベキの構成に最小上界を取る操作を加えたものは完備半束になり
さらにそれは循環的な関手とみなせ、モナドになると書いてあった。
仮にjoinが最小上界を意味しないとすると、理論計算機科学の人たちは、
表示的意味論、束論、圏論、モナドを知りながら、Haskellにおいて、
混乱することが見込まれるのにjoinという用語を持ち出すことになる、
それは、少し考えにくいんじゃないか、と思ったから。
そのあたりの分野って、日常生活でも使うようなありふれている語をテクニカルタームとして使うからなぁ。 ウェブ検索するのにたいへん都合が悪い。 もうちょっと変な語を定義して欲しいもんだ。
>758 > 理論計算機科学の人たちは、 > 表示的意味論、束論、圏論、モナドを知りながら、 関数を書く人全てが,意味論,圏論その他を統一された形で理解しているとは限らないし. 定義を見ると,Control.Monad.join は(圏論の)モナドの構造射のようだから,もっと適した 名前があると思う.「リスト関数の一般化」に分類されているから歴史的な理由で join という名前がついているのだろう. > HaskellのControl.Monad.join(モノイドでは積にあたる) モノイドの積は二項演算だから例示としてあまり良くないのでは?
>>758 数学詳しくないのでよく分からないけど、例えば次のような定義をした場合、
import Prelude hiding (return, fail, (>>=))
import qualified Prelude
import qualified Data.Set as S
class NewMonad m where {
(>>=) :: Ord b => m a -> (a -> m b) -> m b;
return :: a -> m a;
fail :: String -> m a }
instance NewMonad S.Set where {
m >>= k = S.unions $ map k $ S.toList m;
return = S.singleton;
fail _ = S.empty}
join :: (NewMonad m, Ord a) => m (m a) -> m a
join x = x >>= id
a, b, c :: S.Set Int
a = S.fromList [1,2,3,4,5]
b = S.fromList [2,4,6]
c = S.fromList [0,1,2,3]
d :: S.Set (S.Set Int)
d = S.fromList [a,b,c]
e :: S.Set Int
e = join d
-- つづく
この join は Cotrol.Moad のjoin とほぼ同等で、かつ、集合の包含関係を順序関係とした場合の結び(join)になっていると思う。 だから、この場合は概念的に関係があるけど、モナド一般に拡張できるかどうかはよく分からない。
>>760 プログラムを書いた人がどうだったのかはわからないけれど、
Haskellにおいて華形だとみなされて当然な概念であるわけだから、
関与しているそれぞれの分野から注目されるという見込みは立つ。
開発指導層としては、華形のところにうっかり変な名前をつけちゃって
台無しになるなんて事態は避けるのが普通。必ずチェックを入れたはずだ。
でも、μにjoinという名前をつけたということは、何かしら他人を説得できる
理由というか名目があるんだろう。
二項演算ではないけど、型の二重入れ子を一重にしてくれて、図式を比較したら
対応しているところにあたるわけだから、対応しているといっても良くない?
積じゃなくて余積だといわれるのなら分かるけど。
>>762 サンクス。読んでみる。
そういわれてみると、モナドで完備半束を表現できないとおかしい。
でも、μにjoinという だと意味がわかりにくくなるな それでも、μにjoinという で。
>763 トップダウンでライブラリや関数を作る場合はあなたの仰るとおりだと思う. 一方でローカルな関数/一時的な関数を一般化してライブラリに収めた,という場合 諸般の事情でオリジナルの名前が残ったとしてもおかしくない.いつか適切な名前に 改められるべきだとは思うけども. 経緯を知らない状況で「合理的な理由がある」と決め付けることは私にはできない. >762 Control.Monad.join は要素の重複をそのまま残すので,いわゆる集合の join にはならないと思う.
>>761 動かしてみたけど、確かに結び(join)になっているようだ。
意味論とトポロジーは関係あるそうだし、結び目の理論もモナドで実験できる
のかもしれん。全然知らないけど。
>>766 前後した。重複を許すとはどういう風なもの。
Listのjoinはただのfattenだから join [[1,1],[3,4]] は[1,1,3,4] 1は重複してるけど、これが問題になるってこと?
>768 join [[1,2,3],[2,3]] = [1,2,3,2,3] {1,2,3} \/ {2,3} = {1,2,3} ちなみに領域理論で使われるのは general topology で,結び目とかのいわゆる 「トポロジー」とは(多くの場合)大きく異なる. あと,念のために書いておくと結び目は knot/link だからね.
なるほど〜!なるほどぉ〜!
μはleast fixpoint νはgreatest fixpoint っていうのは再帰理論関係の方言みたいなものだから Monadにおいてμでjoinを表わすのはjoinの定義が μ. T T = T になってることから来てるように思えるんだけど 何故greatestじゃなくてleastなのかってのがよくわからん CPO(完備半順序)で μ (T(T(X)) < T(T(X))ってなってるってことなんだけど 直感ではネストが減ってるからとかそんな感じでgreatestはありえんという気はするけど 型付きラムダ計算の世界におけるCPOとしてはもう少し厳密な定義があるはずだよね
>>774 理論的にはそういう感じで推測しました。
もし余モナドがあればjoinじゃなくてmeet(最大下界)になって、
最大不動点を意味するのかなと。
付け加えて、内容を理解していないので言いがたいのですが、 圏論の基礎のp150に積はmeetで余積はjoinだ、という話が書いてあります そこが関係するような。 でもそうすると、joinじゃなくてmeetにするべきのような気がしますね。 (余積の図式なので。)
777 :
デフォルトの名無しさん :2011/02/07(月) 15:56:05
SunOS(SPARC64)上で、darcsを使いたいのですが、どんな準備をすればよい か教えてください。Linuxなどの場合は、 - Haskell Platformをインストールする - それに含まれているcabalを使う という手順のようですが、Haskell Platformのページに行くと、 Windows,Mac,Linuxのみの対応のようです。
最近、忍者さん… どうしてるんやろ・・・・
リストで最初にマッチした要素に処理をしたいです foldではマッチ後も余分な計算が発生するので 次のような関数を考えたのですが 既に用意されてる関数を組み合わせてこういうの出来ないでしょうか (言い換えると、List.anyで最初にtrueになった要素に処理したい) --空リストがあるので、結果は仕方なく1要素からなるリスト dofirst :: (t -> Bool) -> (t -> a) -> [t] -> [a] dofirst pred f lst = case lst of [] -> [] x:xs -> if pred x then [f x] else dofirst pred f xs result=dofirst (==20) (*2) [1..]
import Data.List(find) result = fmap (*2) $ find (==20) [1..]
>>781 dofirst :: (t -> Bool) -> (t -> a) -> [t] -> [a]
dofirst p f = maybeToList . fmap f . find p
これが同じ関数になっているはず。
ただ、これが本当にやりたいことなのか疑問に感じる…
>>780 バトルロワイヤルスレにいるPerl評論家ってのが奴じゃないのか?
>>782-783 短い!エラー処理ではなくMaybeかー
やりたかったことは
dofirst p f = fmap f . find p
こうでした
名前がどうのと言うのであれば、 return がうまくないけど歴史的経緯で仕方がないというのも Haskeller の共通認識だろ。 そんなにキッチリした経緯で決まっていると思わない方がいい。 理論の部分はともかく、用語は人間的な感覚の影響を受けるし。
return はうまくないというか、最大の汚点だと思うが、 もう今更だから諦めてるよね、みんな
returnが汚点なんて誰が主張しているのよ?
>>788 return という名称がダメだというのはみんなも認めるだろ
>>790 理由としてはどういったものがあるの。
自分は結構マッチしていると思っているのでダメだというのがわからない。
プログラマは return と聞くと脊髄反射で関数の戻り値を想像するけど、この return は関数の戻り値とはまったく無関係だから let f = return "test1" >> putStrLn "test2" >> return "test3" >> putStrLn "test4" fの戻り値は "test1" でも "test3" でもない
個人的にはm a -> aのほうが、まだreturnしてるなぁと思う。コモナド
do 記法とセットで使うときになんとなく C とかで言う return と似た雰囲気になる気がする、という程度。
>>795 入門者にそう勘違いさせてしまうのが return の最大の問題だ
>>793 >>=をコマンドラインのパイプのように理解しているから。
return aでaをパイプで処理できる形に変換
>>= f で処理可能にしたaに対してfを適用、で考えている。
>>798 計算を返すという意味でC/C++のreturnとも合致していると思うが。
例えば1をパイプでつないでcatすることを考えた場合 > 1 |cat というのはできない > echo 1 |cat としなくてはいけない。 入出力をたとえとして出しちゃっているので多分変な誤解が出るけど、 言いたいことは、ここでいうechoにあたるのがreturnだという意図なのだと思う。 echo :: 何か値 -> 入出力 だけど return :: 何か値 -> モナド(というかコンピュテーション) と一般化したものだと理解している。正しいかどうかは知らない。 だけど、そんな感じの論理でreturnと決まったんじゃないのかなぁと。
return が圏論的用語とどうこう、手続き型言語のreturnと云々はともかく、Hakellのクラス体系のMonadがApplicativeのサブクラスでないのは審美的に気持ち悪いで、なんとかして欲しい。 WrapMonadとか意味わからなすぎる。 あと、Functorクラスの(.)とidは別のクラスにしておけとか、ArrowクラスのarrがArrowChoiceと対称性を損なっていてキモイとか。
>>785 foldlだと駄目だと思うけど、foldrだといけるんじゃ?
dofirst p f = foldr k Nothing
where k a b = if p a then Just (f a) else b
-- dofirst (==20) (*2) [1..] => Just 40
dofirst' p f = foldl k Nothing
where k b a = if p a then Just (f a) else b
-- dofirst' (==20) (*2) [1..] => _|_
「return 0」 は 0 を返してるんじゃなくて、 整数型の0をモナドに入れて別のモノに変換してるんだよね
>>801 理論的に美しいとか別にどうでもいいよ。
実用的に便利な組み合わせがあるのならそっちを優先するべきだし。
そもそも満足に綺麗に出来る保証なんてない。
自分は一般的に使えそうなところを探しているだけだよ。
目指すなら無駄のない機能美だよ。 机上と実践じゃ必ずギャップ出るんだから。最初から現実的な落とし所で 考えておいたほうがリスクが少ないよ。
実用的じゃないものよくやられるねクズどもは かわいそうだね 言語オタとか死ねばいいよこういうやつら 何もつくれねえじゃん なに作ってるのかな? エジソン気取ってんの?笑
>>804 ,805
そりゃ、理論的な美しさと実用性を比べれば実用性のほうが勝るかもしれないけど、MonadがApplicativeのサブクラスでないことは、実用性も損なっていると思うな。
ライブラリ製作者が注意すればよいこと、Contorl.なんちゃらカコイーな変態(オレとか)がいちいちinstance宣言かけばよいことではあるが、それでも僅かにであっても実用性を損なっている。
>>806 変態で悪いか? あぁ、悪いのか? オレが変態でお前に迷惑かけたか?
ああ、オレは変態だよ。それが何か問題か?
平日の深夜に 2ch で煽ってる人はどういう人だろう
>>806 芋(IMO):
- OCamlはネイティブバイナリ作るときにコンパイル時に使用するライブラリライセンスはLGPL (商用アプリ作るときに色々と面倒)
- 今後ゲーム開発は関数型言語が主流になるかもしれない話や研究活動は数年前からある。Haskellはその候補のひとつと考えている。
- 探すと意外と使われているし、開発も盛んである。あと俺のところで立ち上げる予定のサービスにC/C++, Perl, Ruby, PythonではなくHaskell使う予定だから(変態Haskell初心者で何が悪いか!)
- HaskellでOSを書いている人はたしか実在する。Houseだっけな。つまりGHCを使用してシステム記述にも使おうと思えば使える。
要するに頭の悪い否定癖を捨てて物事を両面から見ろってことだ。
凄くっても取っ付き辛いと普及はしないんじゃないかな
return が変と言ってる人達(俺も含めて)は、 return が行う事、return が担っている役割が変なのではなく、 そういうものに return という名前が付いていることに違和感を感じている(と思う)
自己レス
>>801 (.)とidは、Categoryクラスでした///
>>801 (.)とidを別のクラスにするのはどうして?
射の結合(.)とその単位元(id)は切っても切れない関係のような気がするけど。
>>811 とっつきにくさは情報の整備によりある程度は解決するので
時間とコミュニティの方針の問題かな。
あと必要なら何故か存在しないGHCのユーザーズガイドの完訳を半年程度で
やるけど成果と最新安定版とのバージョン同期は期待しないでね(他も一人でやると半年では終わらない)。
>>802 遅延評価!foldでは無理だと思っていました。なるほど、不思議
再度挑戦して
dofirst2 pred f x = find pred x >>= return .f
を経て
dofirst3 pred f = liftM f . find pred
→liftMとfmapって似てるなと思っているところです
>>813 > 射の結合(.)とその単位元(id)は切っても切れない関係のような気がするけど。
圏としてとらえるならば(それはCategoryクラスの名前にかなったこと)、たしかに(.)とidが必要。
でも、圏としてとらえる以前に連結? 合成? できる有向グラフとしてとらえることもできるはずで、その場合は(.)はいるだろうけど、idはいらないんじゃないかな。
議論のために考えた例だけど、例えば
data Foo = Foo ...
data Bar a b = Bar {
runBar :: a -> (b, Foo)
}
のような型があった場合、Barに(.)を定義するのは簡単だが、直感的に自然な形でidが定義できるとは限らないでしょう?
>>815 ここ↓によれば
http://snak.tdiary.net/20091020.html fmap = liftM は、FunctorでもMonadでもある型では必須の要件らしい。
関手のように取り扱いできる じゃおかしい 関手を適用したように取り扱いできる で。
>>816 サイト情報ありがとうございます。
>>728 の型みたいにFunctorはMonadを含んでいる(機能的にはFunctor⊂Monadだけど)ので
常にMonadはFunctorのインスタンス、ってことなのかな
ただ、実装でそれを強制されてはいない(と思う)ので
より特殊化されているliftMを使ってる方が安心な気がします
ところでポイントフリーを調べていて、W(\x y -> x y y)コンビネータに行き着いたのですが
前に話題になったjoinの型 μ:m (m a) -> m aは、Wの型(a -> a -> b) -> a -> bと対応してるそうですね
(m aは1引数関数と見なせるので(a -> m -> m) -> (a -> m)と見ると型は近い)
ttp://stackoverflow.com/questions/4333864/trick-for-reusing-arguments-in-haskell >>728 の型も眺めてみるとη:a -> m aはK(あるいはKI)コンビネータと対応してるように見えなくもないし
T(fmapやliftM)もなんかのコンビネータと対応してるのかも
>>817 ごめん。オレには
>>816 以上にうまく説明できないし、オレが何か勘違いしている可能性もある。
関数プログラミングの楽しみという本にArrowのことがちょこっと書いてあったけど、圏論とか関手そのものの説明がはしょってあったので、圏論とHaskellの関係がよくわからなかったです その圏論からモナドまで説明してある本ってないですかね? 本屋にいったけど、圏論の本なかったです
言えないっ いまさら英語が読めないなんて言えないっ
>>826 これは失礼。あったのですか。
他に訳されていないもの探してみます。
お前らの議論についていくには バチェラーだけじゃ無理
お前等の中で、圏論の知識が Haskell でのアプリ製作、 ライブラリ製作に役立ったよ、って経験者はいる?
ポルトガル語専攻だけど、圏論の基礎を買ってきたよ さっぱり分からん
for the working mathematicianだからな 邦題を決めた奴は地獄の業火の中に投げこまれるべきである
>>801 Arrow が Categoryのサブクラスなので (.)とidを Categoryクラスで定義するのはしょうがないと思うが。
> ArrowクラスのarrがArrowChoiceと対称性を損なっていて
これはどういう意味?
>>832 自分の言葉で言わないとわからなくなるだけだよ。
Arrowは全く知らない。機能を難しくしても、個別の機能にまつわる話が
分散化していくだけで、あんまり意味というか仕事にならないと思う。
834 :
801 :2011/02/10(木) 23:51:50
>>832 Arrow から arr を除き、それと ArrowChoice のデフォルト宣言に手を加えると、それぞれのクラスはだいたい次のようになる
class Arrow a where
first :: a b c -> a (b, d) (c, d)
first x = x *** id
second :: a b c -> a (d, b) (d, c)
second x = id *** x
(***) :: a b c -> a b' c' -> a (b, b') (c, c')
(&&&) :: a b c -> a b c' -> a b (c, c')
class ArrowChoice a where
left :: a b c -> a (Either b d) (Either c d)
left x = x +++ id
right :: a b c -> a (Either d b) (Either d c)
right x = id +++ x
(+++) :: a b c -> a b' c' -> a (Either b b') (Either c c')
(|||) :: a b d -> a c d -> a (Either b c) d
Arrowの宣言の first を left に、 second を right に、*** を +++ に、 &&& を ||| に、(a,b) を Either a b に、a b c を a c b に置き換えれば、ArrowChoiceの宣言と全く同じ。
(a,b)が集合の直積、Either a b が集合の直和に相当することを考えても、この対称性(あるいは双対性?)は明白だと思う。
対称性があると思うんだけどどこが「対称性を損なっていて」るの?
ああ arr があるかないかの一点だけが対称性を損なっているという意味か。
Steve Awodey の「Category Theory SECOND EDITION」で圏論を学んでみようとしたが、 途中まで読んでだいぶ挫けそう、というか飽きかけてる 圏論を知っていたから Haskell でこういうプログラムができるようになった、 Haskell のこういう事が理解できるようになったとかいう自慢話は何かない? 圏論を学ぶ道の先に Haskell の輝きが見えるとモチベーションが維持できるのだが
807
>>変態で悪いか? あぁ、悪いのか? オレが変態でお前に迷惑かけたか?
>>ああ、オレは変態だよ。それが何か問題か?
>>807 変態気取り うわ〜お前みたいなやつ人のまね
変態的コード とかいうやつの真似
yusukebeのまね
お前は真似野郎猿真似帰れよ猿
チンパンだね キモ
>>837 10章まで行って、やっとモナド則が必要な理由が分かる程度
役に立った話をしつこく聞きたがってる人 うん、君の役には立たないし義務教育ってわけでもないから 話がわからないなら教室から出ていっていいのに 座り込んで泣くわ喚くわ小便を漏らすわ もうね
しつこくって、
>>837 で初め訪ねたんだが
圏論の Haskell への応用って話は私だけでなく、
他の人も知りたがっている事だと思ってたが、違うのか?
きみは知りたくないのか?
オレも、Haskell の勉強の一環として『圏論の基礎』を買ったけど、すぐに挫折したくち。 ただ、それでも、以前も書いたことだけど、オレは MonadやArrowのdo記法の存在が、圏論による抽象化の小さくない恩恵だと思っている。 他には、例えば、\x -> fmap f1 $ fmap f2 $ fmap f3 $ x = fmap (f1 . f2 . f3) ということにすぐに気が付き、関数を短く書けるということも、圏論による抽象化の恩恵なんだろう、たぶん。 あと、次のような例を思いついた。モノイドを圏に変換しているんだけど、これは(すぐに挫折した)『圏論の基礎』からの知識を使っている。 import Prelude hiding ((.), id) import Control.Category import Data.Monoid data Monoid m => MonoidCategory m a b = MonoidCategory m mc :: Monoid m => m -> MonoidCategory m () () mc = MonoidCategory runMC :: Monoid m => MonoidCategory m () () -> m runMC (MonoidCategory a) = a instance Monoid m => Category (MonoidCategory m) where { id = MonoidCategory mempty ; (MonoidCategory a) . (MonoidCategory b) = MonoidCategory $ a `mappend` b } foobar = runMC $ (mc "Foo") . id . (mc "Bar") -- foobar => "FooBar"
>>840 分からないなら分からないと素直に言った方がいいと思う
>>842 モノイドは圏なのに、圏に変換する理由が分からないです
あと、「圏論の基礎」は日本語がおかしい
こんにちは。
学校でHaskellを選択して今
>>4 の・Haskell: The Craft of Functional Programming を読んでいます。
それで少し分からないのが
square ::Int ->Int
square n= n*n
です。
すみませんが中々分からないので教えていただけませんか?おねがいします。
それの何がわからない?
うーん、皆が理論的な話をしている中でアレだけど、やっぱりcabalがパッケージの依存関係を壊すことが納得できない。
ソースコードとコンパイルしたプログラムが1対1じゃないのが気に食わない。
http://cdsmith.wordpress.com/2011/01/16/haskells-own-dll-hell/ この記事の3. Can we stop cabal-install from breaking the package database?
の項目でcabalが依存関係を壊す典型的な例を出してるけど、例えば二つのhaskellプログラム、
yiとかgititとかの、たくさんの依存パッケージを持つ応用プログラムを同時に入れようとすると確実に壊れる。
・cabalが無闇にパッケージのリビルドをしない
・ghcが同じソースコードのビルドで違うid,hashを作らない
どっちかで解決できるはずなんだけどなあ。
QuickCheckがあるから強気に出てると推測
err 関数や undefined 関数は副作用を持つのか、持たないのか・・・ ちょっと気になった まぁ、ホントどっちでもいいことだが
>>846 あなたが何が分からないのか、こっちには分からない・・・
一行目の「square :: Int -> Int」は型宣言。
「関数 square は、32bit符号付整数型を受け取って、32bit符号付整数型を返す関数ですよ」と、関数 square の『型』を宣言している。
(Intが何bitかは、厳密には環境依存だったはずだけど、たいていは32bit)
二行目の「square n = n * n」は関数宣言。
「関数 square は、ある値(n)を受け取って、それを n * n と計算して返す関数ですよ」と、関数 square の『実装』を宣言している。
「*」は四則演算の乗法(掛け算)だから、n * n は n の二乗を計算している。
もしかして、「型」というものが分かっていない?
>>848 よく分からないんだけど、
> ?Package foo depends on bar-0.5 and baz-1.2.
> ?Package flox depends on bar-0.5 and baz-1.1.
> ?Package bar-0.5 depends on baz, but has no preference between versions 1.1 and 1.2.
fooは、bar経由で間接的にbaz(に含まれるモジュール)をインポートしており、それとは別に自分で直接bazをインポートしており、自分がインポートしているbaz-1.2と整合させるために、baz-1.2に依存するbar-0.5が必要。
floxも同様に、自分がインポートしているbaz-1.1と整合させるために、baz-1.1に依存するbar-0.5が必要。
でも、bar-0.5は一つしかないので両方の要件を満たすことはできない、という問題だと理解してよい?
>>851 うん。
>>848 の記事にもあるけど、.cabalファイルのバージョン指定がパッケージによって厳しすぎる/緩すぎるのも一因。
で、殆どのパッケージ、応用ソフトがそんな依存関係を持ってる。
ttp://www.mail-archive.com/[email protected] /msg72276.html このCabal dependency hellのスレッドも似たような問題の話をしてる。
hackageに上げたパッケージは、バージョンを変えずに.cabalファイルの記述を変えることができないのが問題だとか、
いやそういう修正をするならfoo-0.5をfoo-0.5.1と微修正してくれるよう開発者にお願いすればいいとか、色々言われてる。
個人的にはパッケージャーが全バージョンの動作検証をするのは大変だから、利用者の報告、検証をもっと簡単にできた方がいいと思う。
他には、自分の使ってるディストリだと内部のソースの変更ではない、パッケージ情報の変更だけとかの場合、
バージョン番号の他にあるリリース番号を上げて対応するとかしてる。依存関係の記述にリリース番号を含むことはできなくしてる。
ここのスレは害 見るだけで頭が痛くなる
おいおい、忍者から評論家へジョブチェンジかよ 技が引き継がれてると鬱陶しいな
>>850 error :: [Char] -> a
error s = throw (ErrorCall s)
undefined :: a
undefined = error "Prelude.undefined"
throw :: Exception e => e -> a
throw e = raise# (toException e)
というわけで、raise# の意味論や実装に依存。
意味論としては、よく説明されるように_|_という特別な値がすべての型に含まれていて・・・ という理解でひとまず十分で、その視点では副作用は存在しないんだと思う。
raise# の実装は、たぶん普通のラムダ計算の枠組みに収まらないものになっているだろうけど、それを「副作用」と呼ぶのが適切かはよく分からない。
>>851 >(Intが何bitかは、厳密には環境依存だったはずだけど、たいていは32bit)
64bit版のLinuxではIntは64bitみたい。
Cのintは32bitのままだから、ちょっと意外だ。
64bit版Windowsではどうなってるのかな。
次のような関数を作りました。 fix :: (a -> a) -> a -> a fix f x = let y = f x in if x == y then x else fix f y この関数 fix に例えば次のような関数を適用させるとします。 f :: a -> a f x = if {x を使った述語} then x else {x を変化させた値} fix f {a 型の適当な値} とやったとき、 もし関数 f の {x を使った述語} が真なら x そのものを返していますが、 それでも関数 fix 内の x == y では a 型の同値関数 (==) が適用されます。 この場合、x と y は同じものを指しているにもかかわらずです。 この挙動は当然と言えば当然なんですが、値ではなく、指している対象同士で 同じかそうでないかを比較する仕組みは作れないものでしょうか。 というのも、実際のところ a 型に相当するのが画像データを格納した けっこう大きな Array 型なんです。 Array 型のソースを見てみましたが、(==) 関数の定義は重そうですし、実際重いです。 指している対象同士で比較できれば処理速度が速くなるのですが。
やっぱここだと話がまとまらん。 どこか別に話ができるところとかないもんですか。
>>857 モナディックになってしまうが、MArray のインスタンスを使うのはどうだろう?
import Data.Array.IO
import Control.Monad
fix :: (Eq a, Monad m) => (a -> m a) -> a -> m a
fix f x = do
{ y <- f x
; if x == y then return x else fix f y
}
f' :: Monad m => (a -> m Bool) -> (a -> m a) -> a -> m a
f' p k x = do
{ b <- p x
; if b then return x else k x
}
f = f' (getBounds >=> return . (0==) . fst) (\a -> writeArray a 0 100 >> return a)
main = do
{ x <- newListArray (0, 10) [0..] :: IO (IOArray Int Int)
; y <- fix f x
; assoc <- getAssocs y
; print assoc
}
つづく
>>859 >>860 > なので、 IOArray や STArray を使っているかぎり、(==)は要素の比較のみしてくれるはず。
要素の比較ではなくて、参照で比較するから速いんですよね。
アドバイスを受けてから調べてみましたが、こんなページを見つけました。
http://www.macs.hw.ac.uk/~dsg/gph/docs/4.06/users_guide/ghc-language-features.html ここにも、要素同士の比較ではないと書かれていました。
> モナディックにするのがいやなら、配列を生成/変更するときにハッシュ値でも計算してそれを比較するようにするとか。
なるほど、そういう方法もありますね。
今思いつきましたが、どこがどう変更されたのかは知る必要は無く、
直前のものから変更された事だけ分れば十分なので、生成変更するたびに
2値の On Off スイッチみたいなものもをいっしょに記録しておく手もありそうです。
前回が On で今回も On なら終了とか。
両方の方法で試してみます。
アドバイスありがとうございました。
>>861 > 要素の比較ではなくて、参照で比較するから速いんですよね。
あれ? なんで、「要素の比較」なんて書いたんだろう。
おっしゃるとおり、「参照の比較」の誤りです。ごめん。
863 :
デフォルトの名無しさん :2011/02/15(火) 00:27:53
いったいいつになったら日本語ネイティブ対応するんだよ!
IOモコナ
日本語に対応させる必然性が感じられないよな
>>865 ふたばみたいなBBSつくりたいんだけど、
今は、むりやり日本語を数字にコーディングしてデータベースに保存してる
AAがあるので、Shift_JISを扱いたいです
YassieとAphaiaの対立の本当の原因って何なの? 例の氏名公開事件は完全にAphaiaに問題があると思うけど、Yassieがあそこまで激しく嫌悪しているのは、それじゃないでしょ?
869 :
868 :2011/02/15(火) 13:33:24
ごめん。誤爆。 ほんとうにごめんなさい。
ハスケルが今一つ流行らないのは Haskellくだ質スレが無いから
かわいそうだねぇ・・・なんどみても
デッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデ r'ニ;v'ニ;、 デッテイウ _,!゚ ) i゚ ) .iヽ デッテイウ デッデデッデ r=、r=、 / `ヽ,. ┘ ヽ デッデデッデ デッテイウ ,、 ,、 .__{゚ _{゚ _} i ′′ } , - (゚(゚ ))> /´l r `'、_,ノi、 l、 、 ,! デッデデッデデッデデッデデッデデッデ r-=、( '' ,r'⌒゙i>_{ ) ヽ.____,ノ` 、 ! デッデデッデ `゙ゝヽ、ヽー´ ,,ノ::``、 _.r(_ ノ゙`ー. ヽ,.┬/ | /7 デッデデッデデッデデッデ にー `ヽ、_ /::::::::ィ"^゙リ-r _,,ノ ,. lー' /ニY二ヽ デッテイウ ,.、 `~iヽ、. `~`''"´ ゙t (,, ̄, frノ `ァ-‐ /( ゚ )( ゚ )ヽ ゝヽ、__l::::ヽ`iー- '''"´゙i, ヽ ヽ,/ / /⌒`´⌒ \ デッデデッデ W..,,」:::::::::,->ヽi''"´::::ノ-ゝ ヽ、_ノー‐テ-/ i | (-、 |  ̄r==ミ__ィ'{-‐ニ二...,-ゝ、'″ /,/`ヽl , ヽ___ノ | ト- :、 lミ、 / f´ r''/'´ミ)ゝ^),ノ>''" ,:イ`ヽ | |r┬ー| l ,/;;;;;;;;;;;;`゙ ! ヾ .il l l;;;ト、つノ,ノ / /:ト-"∧ l | / //;;;;;;;;;;;;;;;;;;; . l ハ. l l;;;;i _,,.:イ / / ,レ''";;;;;ヾ二,-;;´;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 人 ヾニ゙i ヽ.l yt,;ヽ ゙v'′ ,:ィ" /;;;;;;;;;;;;;;r-'"´`i,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; デッデデッデ r'"::::ゝ、_ノ ゙i_,/ l ヽ ゙':く´ _,,.〃_;;;;;;;;;;;;f´' ll;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ` ̄´ / l ヽ ヾ"/ `゙''ーハ. l;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; / l ゙t `' /^t;\ ,,.ゝ;;;;;;;;;;;;;;;;;;;;;;;;;;;
>>871 a -> State s a じゃない?
872 :Perl忍者 ◆M5ZWRnXOj6 :2011/02/16(水) 00:55:33 かわいそうだねぇ・・・なんどみても 873 :Perl忍者 ◆M5ZWRnXOj6 :2011/02/16(水) 00:58:42 デッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデデッデ r'ニ;v'ニ;、 デッテイウ _,!゚ ) i゚ ) .iヽ デッテイウ デッデデッデ r=、r=、 / `ヽ,. ┘ ヽ デッデデッデ デッテイウ ,、 ,、 .__{゚ _{゚ _} i ′′ } , - (゚(゚ ))> /´l r `'、_,ノi、 l、 、 ,! デッデデッデデッデデッデデッデデッデ r-=、( '' ,r'⌒゙i>_{ ) ヽ.____,ノ` 、 ! デッデデッデ `゙ゝヽ、ヽー´ ,,ノ::``、 _.r(_ ノ゙`ー. ヽ,.┬/ | /7 デッデデッデデッデデッデ にー `ヽ、_ /::::::::ィ"^゙リ-r _,,ノ ,. lー' /ニY二ヽ デッテイウ ,.、 `~iヽ、. `~`''"´ ゙t (,, ̄, frノ `ァ-‐ /( ゚ )( ゚ )ヽ ゝヽ、__l::::ヽ`iー- '''"´゙i, ヽ ヽ,/ / /⌒`´⌒ \ デッデデッデ W..,,」:::::::::,->ヽi''"´::::ノ-ゝ ヽ、_ノー‐テ-/ i | (-、 |  ̄r==ミ__ィ'{-‐ニ二...,-ゝ、'″ /,/`ヽl , ヽ___ノ | ト- :、 lミ、 / f´ r''/'´ミ)ゝ^),ノ>''" ,:イ`ヽ | |r┬ー| l ,/;;;;;;;;;;;;`゙ ! ヾ .il l l;;;ト、つノ,ノ / /:ト-"∧ l | / //;;;;;;;;;;;;;;;;;;; . l ハ. l l;;;;i _,,.:イ / / ,レ''";;;;;ヾ二,-;;´;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 人 ヾニ゙i ヽ.l yt,;ヽ ゙v'′ ,:ィ" /;;;;;;;;;;;;;;r-'"´`i,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; デッデデッデ r'"::::ゝ、_ノ ゙i_,/ l ヽ ゙':く´ _,,.〃_;;;;;;;;;;;;f´' ll;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ` ̄´ / l ヽ ヾ"/ `゙''ーハ. l;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; / l ゙t `' /^t;\ ,,.ゝ;;;;;;;;;;;;;;;;;;;;;;;;;;;
自己記述的とは実に素晴らしい
877 :
デフォルトの名無しさん :2011/02/16(水) 14:47:01
カーゴ・カルトって何?
ググれ
Stateモナドの勉強中です。 import Control.Monad.State data Player = Player {hp :: Int} deriving Show addHP :: Int -> State Player () addHP h = do oldp <- get put $ oldp {hp=(hp oldp)+h} return () こんな感じのaddHPの途中でIO処理(例えばputStrLn "HPが加算されました")をするにはどうすればいいんですか? できれば実際にコードを書いてください。 よろしくお願いします。
880 :
879 :2011/02/16(水) 17:03:37
もしかしてこんな感じですか? addHP :: Int -> StateT Player IO () addHP h = do oldp <- get liftIO $ putStrLn $ "OldHP: " ++ (show$hp oldp) put $ oldp {hp=(hp oldp)+h} return () main = runStateT (addHP 7) (Player 8) >>= print
>>874 解決しました。ありがとう
>>879-880 普通のやり方がどうなのかわからないけど
動くものを練習で書いてみました
data Player = Player {hp :: Int} deriving Show
pgen hp = (put (Player hp))>>=(\_ -> return( putStrLn ("Player hp:"++(show hp))))
infixl 6 +>
(+>) st aug=
let dummy = Player 0 in
let player = execState st dummy in
let next =(evalState st dummy) >> putStrLn ("hp +"++show aug) in
let updated = player {hp= (hp player) + aug} in
State (\x -> (next,updated))
display x = let r = runState x (Player 0) in
fst r >> putStrLn (show $ snd r)
main = display $ pgen 10 +> 1 +> 1000 +> 100
>>880 たぶん、理解しているんだろうけど、main の 最後の print がオレを不安にさせる。
"OldHP: ..." を表示させたいだけなら、それはいらないよ。
それと、addHP の 最後の return () もいらない。
そのほか、オレなら、こういう感じに書くかな。
addHP n = do
Player m <- get
liftIO $ putStrLn $ "OldHP: " ++ show m
put $ Player $ n + m
>>881 MTL のバージョン、古くない?
オレの環境(2.0.1.0)だと、Stateデータコンストラクタはエクスポートされていないみたいなんだけど。
で、pgen の >>= は >> に変えられる。
+> は オレならこう書く:
(+>) :: State Player (IO ()) -> Int -> State Player (IO ())
st +> n = state k
where
act = putStrLn $ "hp +" ++ show n
k s = let (act', Player i) = runState st s
in (act' >> act, Player $ i + n)
>>882 演算子の定義の仕方と、dummyが要らない書き方がとても参考になりました
whereのほうが宣言的に見えますね
mtlのバージョンは1.1.0.2(HaskellPlatformの付属品)でした
道理でStateコンストラクタを使ってるコードをあまりみないわけか
Readerのコンストラクタが使えるのに気づいて
類推から使ったら動いたもので
ひゅひゅっだよ みんな、あさだよ
ひゅ〜 ひゅ〜 いぇ〜い
リストのn番目の要素を更新する(n番目の要素を更新した新しいリストを返す)方法を教えてください。 それとも頻繁な更新にはリストは不向きですか?
リストをxs、n番目に置き換える新しい要素をxとすると take n xs ++ [x] ++ drop (n+1) xs
f xs n x = [if i == n then x else e | e <- xs | i <- [0..] ]
>>886 頻繁に更新するなら Data.Map のほうが効率的。
890 :
デフォルトの名無しさん :2011/02/17(木) 17:46:44
>>885 浜崎あゆみとかノネナールキツいよおじちゃん
桃の天然水の人だと思った漏れはいったいどうしたらいいですか
>>886 ハスケル詳しくない俺が答えるけど
ハスケルは参照透過性の為に基本、更新=新しく作り直し
だから遅いよ。膨大なデータを一カ所書き換えるが為に
別のメモリ空間に変更無しの所まで一からコピーし始める様を想像してみなよ
頻繁な更新には向かないね。
勿論策はある。それは他の人たちが答えてくれるよ
>>891 あ、小室てつやに振られてメンへラになった女の方だっけ?
いずれにせよ加齢臭するわ
>>892 > 膨大なデータを一カ所書き換えるが為に
> 別のメモリ空間に変更無しの所まで一からコピーし始める様を想像してみなよ
普通の実装だと、変更無しの所まで一からコピーされはしないよ
変更ヶ所の部分だけ、ポインタを指し替えるだけ
>>894 あり^^
走査はあるの?
ここは前と同じだからパス
ここもパス
:
あ、ここは変更点ね。新規生成してポインタ差し替えます
ここはパス
ここもパス
:
はい終わり
膨大なリストになるとこれでも馬鹿にならないコストでは?
>>892 こんな感じで、詳しく無いとか、わかる範囲とか
そういう答え方しか出てこないのが怖い
haskell刷れ
ひゅひゅだよ みんな、ばん御飯の時間だよ
>>895 君は
>>892 で、ハスケルは参照透過性の為に更新=新しく作り直しだから遅いと言った
その事を理解する比喩として「メモリ空間に変更無しの所まで一からコピー」を挙げた
私はその比喩が妥当ではないと言っている
明らかに私の言い方が悪かったために正しく伝わらなかったのは認める
たとえば x = [a, b, c, d, e] というリストの3番目の要素である c を v に変えるとする
それをコンピュータで実現するための方法は様々あるが、(少なくとも)モダンな実装では、
メモリ内に [a, b, c, d, e] と [a, b, v, d, e] の両データを存在させるようにはなっていない
つまり、[a, b, c, d, e] と同じデータをもう一部コピーし、
その中の3番目の要素を v に変えるなんてことはしない
リスト は [a] -> [b] -> [c] -> [d] -> [e] -> Empty というポインタの数珠つなぎだから、
[b] -> のポイント先を [v] -> [d] -> [e] -> Empty に指し替えるだけだ
[a] も [b] も [d] も [e] も、メモリ内にはひとつしか存在しない
たしかにn番目の要素を変えるには、「普通は」1番目、2番目と辿っていく必要があるため、
君の
>>895 の感覚は妥当だ(それが正しい「遅い理由」だ)
しかし、
>>892 の比喩は、そのようなリスト操作が遅いことを理解する比喩としては全く的外れだ
メンヘラの言う訳のわからない世界はあった。 現実世界ともう一つ、訳のわからん世界の二層構造だったということだ。
おまえら、どんだけ混乱してんだwwwww
あるリストから一部変更したリストを作成する場合、一般的には
・ コンスセル(コンテナ、データコンストラクタ(:))の中身を書き換えるだけで足りるとは限らず、たいていは新しいコンスセルが必要。よって、
>>898 は間違い。
・ 既存のコンスセルと同じ数のコンスセルが必要とは限らず、たいていはそこまでの数は必要ない。よって、
>>901 も間違い。
0 : 1 : 2 : 3 : [] というリストがあるとするだろ。
これの二番目の要素を5に書き換えた新しいリスト、つまり 0 : 5 : 2 : 3 : [] を生成するとする。
この場合、 0 : 1 : 2 : 3 : [] と 0 : 5 : 2 : 3 : [] の後半 2 : 3 : [] はコピーする必要も新規作成する必要もない。
そのまま参照先として共有できる。少なくとも、参照透明なHaskellではそう。
だから、新しいコンスセルを強調すると 0 『:』 5 『:』 2 : 3 : [] で、この場合、新しいコンスセルは、二つ必要。
必要なコンスセルはゼロでも、四つでも、五つでもない。
二つ。
ドリフ(笑)
905 :
デフォルトの名無しさん :2011/02/17(木) 23:51:41
何故かメモリを数百MB食うようなプログラムってどうすりゃいいんですか? プロファイルとって何処がヒープ使ってるのかがわかっても、いったい何故なのかがわからないから 直しようがないという…… いやこれだけじゃ回答しようがないとは思うんですが、実際原因に検討すらつかないから相談も難しい。
>>906 可能性の話しかできないけど。
とくに思い当たる節がないのなら、リストのクロージャが大変なことになっているのかもしれない。
リストの操作を手書きでできるだけ一個のfoldrにまとめたらうまくいくか、それに取り組むことで原因が分かるかもしれない。
909 :
906 :2011/02/18(金) 13:13:18
SCCで分析したけどやっぱり解決法がわかりません。
誰か親切な人、軽いヒントだけでいいのでください。
ttp://codepad.org/WBOniwhN (ICFP 2006の問題)
total alloc: 777,686,388 bytes
parseInst関数: alloc 20%
setRegVal関数: alloc 26.1%
spinCycle-newm(SCC): alloc 17.1%
>>907 ありがとうございます。
リストを捨ててData.Sequenceにしたら少しマシになりました。
>>908 SCCって初めて知りました。
便利なので今試してます。
ありがとうございます。
910 :
Perl忍者 ◆M5ZWRnXOj6 :2011/02/18(金) 14:03:19
ひゅひゅだよ みんな、おやつは何んですか?
きのこの山
圏論が理解出来てないやつはhaskellを使う資格は無いな。 俺はそう思う。
913 :
Perl忍者 ◆M5ZWRnXOj6 :2011/02/18(金) 15:09:39
>>ライトニングトークスでUjihisa君の話「JavaScriptとHaskell」が興味深かった。 Haskell読書会に出たものの、どうしてもHaskellのソースは読めなかったけれど、 JavaScriptで置き換えてくれてようやく、Haskellが分かった気がした。 なんでjavascriptやてるやつがわざわざ,Haskellやって まわりの奴がjavascriptで置き換えてあげないといけないの? ばかなんじゃないの? こいうやつは、すぐハテナの影響うけて いろいろな言語わめきだすやつだろうwっっっっっっっっっっっっっっっw
>>909 Sequenceの代わりにIOArrayを使い、全体を StateT UM IO みたいなモナドにして、手続き的に処理するようにすれば改善するじゃないかと思う。
Haskellで手続き的にするのはどうなのよ、という気もするし、場合によっては性能が悪化すると思うけど、おそらく出題が手続きを前提としているので、この場合は改善するんじゃないかな。
915 :
909 :2011/02/18(金) 18:17:37
>>914 ありがとうございます。
それだと確かにSequence.update使ってる辺りが軽くなりそうですね。
ただ、parseInstはそれだと変わらない気がします。
(というかparseInstみたいな単純な関数がどうしてこんなメモリ食うのかわからないです)
Word32のかわりにWord#を使ってそれに関連する関数をPrimOpにし Instの各フィールドを!付きのstrictなものにするとか?
ひゅひゅだよ 晩御飯の時間だよ
918 :
909 :2011/02/18(金) 20:46:12
#haskellで質問してきます。
>>916 ありがとうございます。
Word#がよくわからなかったのでとりあえずInstの全フィールドをstrictにしましたが
多分何も変わってない感じです。
Perl忍者の初出はPart12?
わかんないひゅひゅだよ
俺メモ replicate 1が(:[])でいけることを知った scanl(\a->(++)a.(:[]))[][1..9]
922 :
918 :2011/02/19(土) 00:02:41
#haskellで質問して教えて貰ったところ、かなり状況が改善しました。 Before: 500MBとかメモリ食べて事実上途中でフリーズ(私のPCの空き物理メモリほぼ全部) After: 10-30MB程度。 (このプログラム(仮想マシン)が未完成なので正常動作しているのかは不明ですが、別の仮想データを食わせたら100MB-200MB程度使いはするものの 前より先まで計算が進んだので状況が改善しています) 以下、参考までに。 1,{-# LANGUAGE BangPatterns #-}をソース先頭に追加。 2,UMとInstのフィールドそれぞれに!を付けた。InstのWord32は{-# UNPACK #-}つき。 3,setRegValの定義をsetRegVal m ra !vに変更。 4,opAMEND内のletのnewvalueとnewarrayの先頭に!追加。 #codepadのコードっていつまで残るのかな?後でこのレス読む人の参考になるといいんですが。 あとこの場合、メモリ使用量の点ではSeqじゃなくてUArrayもありかもと言われました。 更新速度は当然落ちるみたいですが。 プログラム自体は正常動作しているのか不明ですがメモリ使用量は改善しました。 ありがとうございました。
923 :
みなみな ◆dEQBXko0pE :2011/02/19(土) 09:00:17
ひゅひゅだよ
>>922 その方法で改善する理由も教えてもらった?
つわぶきっていうキチガイいますかぁ!? Tsuwabuki「僕は、Catalystやってますよ wiki程度ならつくれますが」 俺「へぇ〜wwすごいねえwすごいよw そうなんだあw」 Tsuwabuki「DBIとかわかりますよ」 俺「ほ〜wすごいねえ まじ?w haskellやってるのにPerlもできるんだねえw」 とか話きいてたやったけどさあwwwwwwwwwwwwwww こいつカスだよwwwwCatalystとかわめいててwwww そしたら俺を上から目線でみてきて、連絡こなくなったしさww 自分のほうがレベル高かったからおちょくってやったよ
ここにスカイプID晒してからさwww Tsuwabukiから連絡きたんだよwwwwwタイミング的にあれだしw ハンネぐぐったらhaskellやってるとかツイッターでてきたしさw ここ見てるやつはTsuwabuki確定だよwwww
a->m bによく遭遇するので、こういうの考えてみた 使い分けは モナド適用前:foldM モナド適用後:onM onM f a [] = a onM f a (x:xs) = onM f (do{y<-a;f y x}) xs onM (\acc x -> return (x acc)) (Just 1) [(*2),(*3),(+1)] foldM (\acc x -> Just $ x acc) 1 [(*2),(*3),(+1)]
モナドとかいみわからねえからさ やめちまえ 論理家きどってんじゃねえぞかす
929 :
918 :2011/02/19(土) 20:07:29.55
UArrayにしたらメモリ消費量がさらに大幅に減ってアクセスが速くなったのはいいけど予想通り今度は更新が遅い。
IOVector(Unboxed)+unsafeRead,unsafeWrite等にしたらメモリ消費量も少なくアクセス、更新共に速い。
(ただしIOモナドだらけに。そしてモナド内でのwriteがなんか気持ち悪い。)
データ構造の選び方次第でも全く速度やメモリ消費が違うんですね。
無視できない差です。
>>922 ききませんでした。
はいはい、自分の頭の悪いのひがんでもしようがないでしょ?
更新の速度を重視するとなると結局IO, unsafe地獄は避けられないのかションボリ 最近発表されたhashing-based containerのスライドでも更新時のArrayのコピーが他の改善点をぶち壊すぐらいのネックになってたし この辺に関して堅牢さを保ったまま速度を出す方法とかあんのかな? Haskellの型システムの中で線形型システムを作ってそれでIO地獄を隠蔽するとかぐらい? bound checkに関してはそれこそstatic contractionとかdependently typeみたいなformal method方面のやりかたを導入するしか無さそう
IOなしで配列の破壊的更新をしたいならSTArray/STUArrayがあるよ 線形型で実現された配列と比べたら柔軟さで劣るけどHaskellの型システムの枠内ですぐに使える Arrayのコピーは単純にGHCのrtsのチューニングでなんとかなるんじゃないかと期待
プリミティブだからrtsのチューニングじゃなくてGHC本体か
935 :
デフォルトの名無しさん :2011/02/20(日) 10:32:47.06
速さが必要な部分はC++で作って Haskellから呼び出すってできないの?
>>935 呼び出すだけなら簡単にできる
双方のメモリアドレスの受け渡しが絡んでくると、扱いが面倒になるが
haskell始めてみたけどやっぱモナド辛いわ test = do w <- [1..(10)] v <- (\x -> [x,x^2]) w guard $ (\x -> x `mod` 2 /= 0) v return v これをdo構文を使わずに書くことは出来るのでしょうか。 そもそも3行目の有無でtestの値が変わる仕組みがよく分かりません。 return v の代わりに return w とした結果もどうしてこうなるのか?という感じで…
そのまま書き換えるとこうかな test3=[1..10]>>=(\w->(((\x->[x,x^2]) w)>>= (\v->(guard $ ((\x -> x `mod` 2 /= 0) v)) >> return v))) guardがやっているのは、条件を満たす個数だけ要素を残すことなので、結果は何でもいい [1..10] >>= (\x->guard (x<5))は [(),(),(),()] Listモナドの>>=動作はconcatMapだが >>でつないだときは、前の要素数分、新しい要素を作ってconcatMap [1,2,3] >> [4,5]も [(),(),()] >> [4,5]も [4,5,4,5,4,5] そして、 do記法で単に{ a;b;c}ってのはa>>b>>cと同じ意味 同じ内容ならこんな感じで [x|x<-[1..10]>>=(\a->[a,a^2]),rem x 2/=0]
>>937 > そもそも3行目の有無でtestの値が変わる仕組みがよく分かりません。
> return v の代わりに return w とした結果もどうしてこうなるのか?という感じで…
次の定義をどこかにメモっておいて、
自分でノートなんかに >>= の式を展開してみると、
より理解が深まる(かも知れない)
-- GHC.Base より
instance Monad [] where
m >>= k = foldr ((++) . k) [] m
m >> k = foldr ((++) . (\ _ -> k)) [] m
return x = [x]
fail _ = []
-- Control.Monad より
instance MonadPlus [] where
mzero = []
mplus = (++)
-- Control.Monad より
guard :: (MonadPlus m) => Bool -> m ()
guard True = return ()
guard False = mzero
>>937 オレはリストモナドを平行世界的に理解している。
test = do
w <- [1..(10)] -- {w = 0}の世界、{w = 1}の世界、{w = 2}の世界・・・、{w = 10}の世界の世界が生まれる
v <- (\x -> [x,x^2]) w --
guard $ (\x -> x `mod` 2 /= 0) v
return v
941 :
940 :2011/02/24(木) 22:23:42.21
うわ、途中送信しちまった。 test = do w <- [1..(10)] -- {w=1}の世界、{w=2}の世界・・・、{w=10}の世界の世界が生まれる v <- (\x -> [x,x^2]) w -- {w=1, v=1}, {w=1, v=1}, {w=2, v=2}, {w=2, v=4}・・・の各世界に分岐 guard $ (\x -> x `mod` 2 /= 0) v -- {w=2, v=2}, {w=2, v=4}・・・ などが失われる return w -- {w=1, v=1}, {w=1, v=1}, {w=3, v=3}, {w=3, v=9}・・・ などの世界が生き残っている いちめん染める花は♪ 空へと昇る光♪ 幾億の息吹たち♪ 今♪ 世界が生まれ変わる〜♪
ここは、遥か天空を超えた天界 gfxが一瞬で倒せる領域、もう神の世界 君たちHaskellは、天界から下界を見て広大な心で迎え入れているのだろう
HaskellのクソザコTsuwabukiでもgfxを瞬殺プログラミングできるレベルなんだろ?
Haskellの凄さはわかったよ 君たちは、ハスクカルド天界、モナド聖騎士団っていう登場キャラで出してあげるから おとなしくしてね
ContTって内側に入れるのと外側から包むのとどっちが早いの?
946 :
937 :2011/02/25(金) 01:01:24.13
ああListモナドの>>ってそういう! 皆さんありがとうございます。 色んな方から視点を貰えて助かりました。 なんとか全て理解できた気がします。 後は慣れじゃー
リストモナドってなんか論理言語っぽいな
Haskellが今ひとつ流行らないのは、バイナリに後方互換性がないから
要因はそれ以外にもあるのは当然として、それの占める割合そのものも小さいとおも
>>947 条件を満たすすべての組み合わせを列挙する、ということが自然に表現できるよね。
>>948 Linuxのディストリビューションとかだと、その辺はパッケージャーが考えること、という気もする。
ただ、実際には、UbuntuのGHCパッケージの放置されっぷりといったら・・・
他のディストリビューションだとどうなのかは知らん。
2人が延々と自演を繰り返してる恐ろしいスレ
>>949 大規模な開発だとライブラリの後方互換性は重要な問題だと思うけど
>>950 言語(コンパイラ)仕様がディストリだのパッケージメンテナだのといった存在に依存してるのはおかしいと思う
せっかくネイティブコード吐けるのに、
I/Fを弄らずにライブラリを改変してもバイナリコンパチが崩れるのは、言語として幅を狭めているのでは
>>746 でも書いたけどトレードオフだよ
Haskellはある程度激しい最適化をしないと使い物にならないことが多いから、
バイナリ互換性を崩してパッケージ間インライン化を取るのは仕方ない取引だと思う
Haskell の最適化って GHC に限ればバイナリ レベルのものは GCC に丸投げなのでは?
激しい最適化はストリームフュージョンとかの中間言語レベルの時だと思うんだが
まぁ、中間言語のファイルをやりとりすることは無く、
実質バイナリ互換性を崩してるという話はその通りなので
>>953 には同意する
でも「このパッケージの関数はインライン展開しなくていいから代わりにバイナリ互換性をよこせ」 みたいなオプションは有り得るよな
だね それから、モジュール中の全ての演算に無条件に正確性を強制するオプションがあってもいい。
すみません さっき、Haskell Platform の最新版をインストールしたんですが、 Text.Regex.Posix の (=~) の [String] ってなくなったんでしょうか? ↓ みたいなのができなくなってました "test" =~ "t" :: [String] Windows7 64ビットです
>>957 regex-posixパッケージを本格的に使ったことないけど、最新の0.94.4ではダメみたいね。
想像するに
getAllTextMatches $ "test" =~ "t" :: [String]
にとって代わられたのかしら。
今までfoldrが末尾再帰だと思ってた 偽りの人生だった
>>959 ワロタ
「偽りの人生」が再帰でないことを祈る
cabal で gtk2hs-buildtools をインストールしてから、 cabal info gtk2hs-buildtools で確認したところ、 Latest version available: 0.12.0 Latest version installed: [ Unknown ] と表示されたのですが、これは正しくインストールされたのでしょうか。 未インストールの状態なら、普通は [ Not installed ] と表示されると思うのですが、 [ Unknown ] はどのような状態なのでしょうか。
>>961 gtk2hsC2hs、gtk2hsHookGenerator、gtk2hsTypeGenっていう三つのコマンドが入っていれば、インストールされているんじゃないの?
Haskellwikiの qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) は、==のテストが冗長な気がするのですが qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (x <) xs) として大丈夫ですよね?
>>963 入力リストの要素に重複がないなら同じだと思うけど、前者はそれがある場合に備えているわけで、べつに冗長ではないのでは?
なるほど、こう書いてしまうとまずいですね List.nub+qsortを混ぜたような処理になるわけか
あれ、訂正。そうはならないけど、中途半端なバグありコードになってしまいますね ありがとうございました
同値性テストに冗長性を感じたのに、 filter で2回もリストを辿ることに冗長性は感じないのかな
先生宿題のクイックソートができました q[]=[] q(x:xs)=arr (List.partition(<x))>>>first q >>> second q>>>arr((((((((((((((app .).).(&&&))(((app .).).(&&&)) (const id)).).).).)((flip.).) ((.).((.).))) .).).).) (((.).(.)).)flip(++)(:) x snd fst ) $ xs
やめろばか
>>968 テラワロスwww
どれくらい時間かかった?
1時間ぐらいかかりました
>>972 1時間もアロー、アローでゴシゴシやってたのかwww
オマエみたいな変態は大好きだwww
研究室にはいらない。
どうしよう、まず読む気がおきないwww
pointfree先生の力を借りて今必殺の if' b x y = if b then x else y qs :: Ord a => [a] -> [a] qs = fix (ap (flip if' [] . null) . ap (ap . ((++) .) . (. ap (filter . flip (<) . head) tail)) (ap ((++) . return . head) . (. ap (filter . flip (>=) . head) tail)))
読みにくい 保守しにくい 教育しにくい 絶対に純粋さが裏目に出てる
1行で150文字超えるとか… もうアホとしか…
最近Haskell勉強し始めたLisperだけど、
>>968 を見てHaskellは色々凄いと思いました。
パズル的な遊びに対してマジレスしなくても・・・
981 :
デフォルトの名無しさん :2011/03/04(金) 17:59:55.90
遊びじゃなくて、オーソドックスにアロースタイルで実装すると
>>968 になるんじゃないの?
クイックソートをアローで表現しようとすること自体が遊びだと思うが
次、haskell自体〜とか禁止だから!!
邪悪なCコードの主催者がこの辺うろついてたの見かけたが 誰かなんかしたのか?
Lazy K コミュニティに行きたかったのに、なぜか勘違いして来ちゃったみたい。
諸君、議論し給え
議論っても、ネタがないことには。 じゃぁ、mapはListの(a->b)->[a]->[b]であるべきか、それともfmapの異名としてFunctor f=> (a->b)->f a->f bにしてしまうべきか。
mapとfmapは別物であるべき派かな俺は
>>988 なんで?
俺は map の型を Functor f=> (a->b)->f a->f b にして、
全部これで統一して(fmap 要らん)たら良かったと思う
分ける事で構文的にあるいは意味論的に美しくなるとも思えないから、
2つもあるのは冗長にしか感じない
であれば、fmap なんて一般的じゃない名前より map に統一してほしい
まぁ今更もう遅すぎるが
fmapにはmonomorphism restrictionがあるんじゃないか
fmapは一般的すぎて読み手に与える情報が少ない (:[])をreturnと書くのと同種の趣味の悪さを感じる fmapという名前が気に食わないなら(<$>)という素晴らしい名前があるよ (<$>)をPreludeに入れるべきという提案なら賛成する
fmapは関手の射関数という意味だ。Functorクラスを特徴付けるにあたって 対象関数と射関数が必要だからfmapは必要だと思う。 無いとしたらどうやってFunctorクラスを特徴付ける?
>>992 989が言っているのは、リスト専用のmapは廃止し、Funtorのfmapをmapに改名して、リストの場合も後者を使えばよい、ってことでしょ。
995 :
994 :2011/03/06(日) 13:37:55.32
関連スレのリストって要るか? リンク先が落ちてないか調べるの面倒なんだが
Haskell脳ができあがった人であれば、fmapだけあればmapはイラネって考えるのは分かるけど、 そうでない初心者がいきなりfmapを使いこなすのは(mapと比べて)難しいんじゃないかと。 Haskellへの門戸を大きく開く意味で、現状の命名法は悪くないと思うんだけどな。
>>998 であれば、
map :: Functor f=> (a->b)->f a->f b
lispMap :: (a->b) -> [a] -> [b]
lispMap = map
こんな感じでいいんじゃないか?
listMap は map をリストの型に特殊化したものなんだけど、
とりあえずはそんな深く考えずに、リストでは listMap を使っておいてね
あとで Functor の意味が分ってきたら汎用性のある map を使っていこう
と言っておけば
>>995 テンプレが肥大化したスレの場合、どっかのフリーなwikiにページを作って
アウトソーシングしたりしてるのをたまに見かける。
>>998 関数定義の内容はどうでも良くて(初心者は関数を使いこなすのが精一杯だから)、
関数の命名法、名前の付け方を言ってるんだけどな。
初心者の常識にズレが少ない、配慮(心配り)という意味で。
少なくともリストというデータ構造は関数型言語の基本であり、ありふれて利用されている。
だからそんなリスト向けにはmapという命名を、理論的には汎用性があっても
初心者には難解な関手向けにはFunctor mapという命名にするのは悪くはないんじゃね。
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。