1 名前:デフォルトの名無しさん mailto:sage [2007/10/30(火) 20:28:13 ] haskell.org www.haskell.org/ 日本語サイト www.sampou.org/cgi-bin/haskell.cgi www.shido.info/hs/ 過去ログ 関数型プログラミング言語Haskell Part1 pc.2ch.net/tech/kako/996/996131288.html Part2 pc2.2ch.net/test/read.cgi/tech/1013846140/ Part3 pc8.2ch.net/test/read.cgi/tech/1076418993/ Part4 pc8.2ch.net/test/read.cgi/tech/1140717775/ Part5 pc8.2ch.net/test/read.cgi/tech/1149263630/ Part6 pc11.2ch.net/test/read.cgi/tech/1162902266/ Part7 pc11.2ch.net/test/read.cgi/tech/1174211797/ ・2chの仕様により、行頭の半角スペースは表示されません。 コードをインデントしたいときは、代わりに または全角スペースを使うことができます。
136 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 19:13:05 ] do cs <- getContents hoge <- getContents putStr hoge ↑のような式を>>=を使って書き直した場合、どのような式になるのでしょうか?
137 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 19:17:43 ] >>136 getContents >>= \cs -> getContents >>= putStr
138 名前:136 mailto:sage [2007/11/14(水) 20:05:49 ] すいません do cs <- getContents hoge <- getContents putStr hoge じゃなくて do hoge <- getContents cs <- getContents putStr hoge の間違いでしたorz
139 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 21:17:45 ] >>138 getContents >>= \hoge -> getContents >>= \cs -> putStr hoge このケースでは(>>=)を使う旨みはないね。
140 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 22:11:24 ] この場合、 A. getContentsを2回やってからputStr B. putStr hogeをやるために1個目のgetContentsをやって2個目のは保留 のどっちの動作になるんだっけ。 遅延評価的にはBだよね?
141 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 22:18:38 ] >>140 IO動作は上から順に(厳密には>>=の左辺から右辺へ)実行される getContentsの動作は特殊で、読み込み自体は文字列が必要とされるまで遅延される だから、順序としては、 1. 1個目のgetContentsが実行され、ハンドルがセミクローズされる。遅延読みのため即座にリターン 2. 2個目のgetContentsが実行され、ハンドルがセミクローズ状態なので例外発生 で、putStrは実行されない
142 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 22:28:25 ] そういう風な動作になるのか。ちょっと勘違いしてた。Thanks
143 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 22:55:19 ] ここってクロスコンパイルネタはスレ違いですか?
144 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 23:11:31 ] ここしかないだろw
145 名前:デフォルトの名無しさん mailto:sage [2007/11/14(水) 23:31:03 ] クロスコンパイルの場合、GHC(6.4.xや6.6.x)のMakefileって修正なしで通りますか? 依存関係を無視したり、更新情報を無視したり、 無いファイルを参照したり、必要なターゲットを生成しなかったりと 明らかに修正しなければならない部分が多々あるようですが
146 名前:143=145 mailto:sage [2007/11/15(木) 00:01:32 ] 私の環境で6.6.1をクロスコンパイルする場合、少なくとも ホスト、ターゲットで共通 ・distrib以下のファイルに実行許可がされていない ・configureでgmpのヘッダ、ライブラリ位置を指定しても途中から無視する ・makeをやり直した場合、すでに生成したファイルで且つ更新の必要がないものでも再ビルドする場合がある ホストでは、 ・libraries/Cabal/cabal-setup/CabalSetup.hcを生成してくれない ・かといってターゲットとして生成したファイルだとundefined referenceが発生するので-keep-hc-filesを指定してCabalSetup.oをリコンパイルしなければならない ・hc-file-bundleする際、libraries/haskell-src/Language/Haskell/Parser.hsという存在しないファイルをアーカイブしようとする (現在ビルド中ですので途中までしかわかっておりませんが)ターゲットでは ・compiler/primop*.hs-inclが空ファイルで生成される ・compiler/stage1にインタフェースファイルが生成されないためpreludeのビルドに失敗する 等が確認できました i386-unknown-openbsd → arm-unknown-openbsdという特殊な環境ということもありますが、 普通の環境ではすんなりクロスコンパイルできるのか疑問に思えました
147 名前:143 mailto:sage [2007/11/15(木) 00:07:35 ] ちなみにOpenBSD-makeではなくGNU-makeを使用しています
148 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 01:19:56 ] Ubuntu上のemacs22+ghc6-6.1でHaskellのプログラムを色々試しているんですが C-c, C-lを実行するとよくEmacsが固まってしまって何の入力も受け付けなく なってしまいます。そのたびにkill -KILLをしているんですが 同じような症状の人はいないでしょうか?
149 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 01:36:11 ] debianですが、固まりませんね。
150 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 03:01:07 ] IORefについて質問です。 do ioref <- newIORef 0 modifyIORef ioref (+1) readIORef ioref >>= print という式の中でmodifyIORef ioref (+1)がiorefの値を変更している仕組みが どうしてもわかりません。予想としては ・modifyIORefを使うと引数の値を変更できると言語の根っこの部分で決められている という事かなと思っているんですが、この考えでいいんでしょうか?
151 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 07:23:12 ] >>150 C言語の例でよければ *ioref=*ioref+1; で変更されるのは*iorefであってiorefではない。 Perlなら $$ioref=$$ioref+1; といった具合で。 Cで詳細に書いてみる。 void modifyIORef(int * ioref,int (*fn)(int)){ *ioref=fn(*ioref); } int add1(int arg){ return arg+1; } int readIORef(int * ioref){ return *ioref; } int main(){ int * ioref; ioref=newIORef(0); modifyIORef(&add1); printf("%d\n",readIORef(ioref)); return 0; } まあ(>>=)の部分(doで省略される部分とか)までより近く書くともっと長くなりますが。 それ以前にかけるかどうかちょっと自信ないけど。 *iorefは変更されてもiorefは1回の初期化時の変更のみということで。
152 名前:150 mailto:sage [2007/11/15(木) 08:04:34 ] >>151 つまりHaskellは、定数だけでなく、変更される変数の値を保存しておくための(つまり再代入可能な) 場所も用意しているということなんでしょうか?
153 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 10:27:06 ] >>152 実装上はその通り。GHCにはヒープ上に変更可能オブジェクトを置くための機構があるし、 多分Hugsも似たようなもの。 一方で、言語について「Haskellは〜用意している」という言い方をするのは誤解がある気がする。 実際、>>151 の言うように、IORefを使っても(Haskellの普通の)変数の値が変更されることはないし、 言語の根幹に変更を迫るような拡張じゃない。 扱える型を限定すれば、自分で(ファイル入出力を使ったりして)IORefみたいなものを書くこともできる。
154 名前:150 mailto:sage [2007/11/15(木) 13:37:19 ] >>153 よくわかりました。ありがとうございます。 今入門HaskellとふつうのHaskellの二冊を読みながら色々試しているんですが もうちょっと詳しい説明が欲しいなと思うことがよくあります。 そこでプログラミングPerlのような ・どのようにHaskellでプログラミングするか ・Haskellはどういう理由でこういう風になっているのか を解説した本が欲しいのですが、テンプレに載っている洋書で↑の内容に 合っている本はないでしょうか?
155 名前:143 mailto:sage [2007/11/15(木) 13:54:41 ] Makefileを読む時間的余裕が無かったのでとりあえず find compiler/stage1 -name ¥*.o -exec rm {} ¥;して make -C compiler boot stage=1 && make -C compiler stage=1したら ビルド&インストールに成功したようです 後でパッケージを作って本インストールするつもりです 日本語のクロスコンパイルのドキュメントが少ないので 作業過程を簡単に書かせていただきたいと思います (需要は無いでしょうけど) うざったいと思われる方は「クロスコンパイル」をNGワードにしてください
156 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 13:56:24 ] >>154 ・どのようにHaskellでプログラミングするか →『Haskell: The Craft of Functional Programming』 ・Haskellはどういう理由でこういう風になっているのか →『Introduction to Functional Programming Using Haskell』 かなあ。両方とも良い本だと思う。まだ全部読み切ってないけど。
157 名前:150 mailto:sage [2007/11/15(木) 21:41:29 ] >>156 その二冊ですね。お金に余裕ができたら買ってみます。 話は変わるのですがHaskellのガベージコレクションは他の言語(java,ruby...) と比べて動作する機会がほとんどないと思うんですがどうでしょうか。 変数の宣言時にしか値を入れられなくて、グローバル変数とスタック上に 載せられるローカル変数でほとんど全てが賄えるなら どこからも参照されていないデータ(ガベージコレクタの対象になるデータ) ができるなんてことはまずないと思うんですが・・・
158 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 22:41:43 ] >>157 そんなことはない。遅延評価のために何でもかんでもヒープに割り当てないといけないので、 Haskellは平均的な言語よりずっと多くゴミを出す。 GHCでコンパイルしたプログラムなら、+RTS -Sstderrオプションをつけて実行すれば GCがどれくらい動いたかが分かる。 適当なプログラムで試してみたけど、約3秒の実行時間中にヒープから700MBほど確保し、 そのうち約9割は第0世代のGCで即座に捨てられてた。
159 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 22:45:57 ] 具体的に数字出されるとびっくりするなw
160 名前:デフォルトの名無しさん [2007/11/15(木) 22:47:23 ] 俺もびっくりしたwww
161 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 23:07:27 ] 700MB? 700mBの間違いじゃないのか
162 名前:デフォルトの名無しさん mailto:sage [2007/11/15(木) 23:15:22 ] 700*2^20 bytesね 741,834,476 bytes allocated in the heap 108,671,480 bytes copied during GC (scavenged) 2,030,404 bytes copied during GC (not scavenged) 13,955,072 bytes maximum residency (11 sample(s)) 1415 collections in generation 0 ( 0.55s) 11 collections in generation 1 ( 0.43s) 32 Mb total memory in use
163 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 01:10:19 ] やさしい Haskell 入門を今見ているんですが 4.4 遅延パターン www.sampou.org/haskell/tutorial-j/patterns.html での最初の例 reqs = client init resps resps = server reqs client init (resp:resps) = init : client (next resp) resps server (req:reqs) = process req : server reqs がどういう意味なのかさっぱりわかりませんorz どうして↑がだめで client init resps = init : client (next (head resps)) (tail resps) だとOKなんでしょうか?
164 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 02:19:04 ] >>162 これって瞬間最大メモリ使用量が700MBってこと?
165 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 02:50:58 ] うさのパソコンはメモリ256MB!
166 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 02:52:24 ] アプリ側がメモリ確保に成功しても、 OS側で本当に実メモリを消費したとは限らないから 調べないと分からないか。
167 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 03:27:46 ] >>164 アロケートされたメモリの数が700MBってことなのだが、実際はgeneration 0に割り当てられた少ないメモリが使いまわされているだけだから、メモリの使用量自体は少ないはず。
168 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 07:15:29 ] >>164 OSから確保したのが32MB 実際のヒープオブジェクトの総量が瞬間最大で13,955,072 bytes コピーGCだからOSから確保した領域の半分以下しか貯められない
169 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 17:49:52 ] StateモナドでunsafeInterleaveIO的な関数って書けますか? do xs <- interleaveState $ sequence $ replicate 3 get sequence $ map set xs で get set get set get setの順になるようなやつ
170 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 18:08:04 ] unsafe禁止令
171 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 18:26:23 ] xs <- sequence $ replicate 3 $ interleaveState get の間違いか? どっちにしても無理だろ
172 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 18:36:40 ] >>171 すいません、間違いでした 無理orz
173 名前:デフォルトの名無しさん mailto:sage [2007/11/16(金) 22:22:17 ] モナドと代数的データ型に的を絞って詳しく扱ってるテキストはないでしょうか
174 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 03:16:48 ] foo >>= bar としたときに実際に>>=がどのインスタンスに定義されている>>=の処理を行うのか、 というのはどうやって決まるんでしょうか?
175 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 07:11:03 ] >>174 型推論。fooの型とbarの型とその式の使われ方が勘案される。
176 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 11:11:46 ] >>175 それはコンパイル時と実行時のどちらでされるものなんでしょうか?
177 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 11:43:58 ] >>176 実行時
178 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 11:57:24 ] ・型推論自体はコンパイル時。 ・ただし、型クラスのディスパッチは実行時まで遅延される。 ・ただし、どのインスタンスについてのコードを生成すれば良いか静的に決まる場合は、 最適化の一環としてディスパッチを省略する。 こんな感じか。
179 名前:174 mailto:sage [2007/11/17(土) 12:49:35 ] >>177 、178 なるほど、静的に型をチェックしつつ、動作は動的に決まるんですね。 ところで 数学パズル ものまね鳥をまねる―愉快なパズルと結合子論理の夢の鳥物語 ttp://www.amazon.co.jp/%E6%95%B0%E5%AD%A6%E3%83%91%E3%82%BA%E3%83%AB-%E3%82%82%E3%81%AE%E3%81%BE%E3%81%AD%E9%B3%A5% E3%82%92%E3%81%BE%E3%81%AD%E3%82%8B%E2%80%95%E6%84%89%E5%BF%AB%E3%81%AA%E3%83%91%E3%82%BA%E3%83%AB%E3%81%A8%E7%B5% 90%E5%90%88%E5%AD%90%E8%AB%96%E7%90%86%E3%81%AE%E5%A4%A2%E3%81%AE%E9%B3%A5%E7%89%A9%E8%AA%9E-%E3%83%AC%E3%82%A4%E3% 83%A2%E3%83%B3%E3%83%89-%E3%82%B9%E3%83%9E%E3%83%AA%E3%83%A4%E3%83%B3/dp/4627019017/ref=sr_1_9?ie=UTF8&s=books&qid=1195271100&sr=1-9 この本を読んだことがある人いますか?関数プログラミングの土台の考え方がわかる本らしいんですが。
180 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 13:28:59 ] >>179 途中まで読んだだけだけどコンビネータの話。 S,K,I とか。Yコンビネータも出てきたかは覚えてない。
181 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 16:07:56 ] a 1 = "hoge" a 2 = 2 のような引数によって異なる型の値を返すことはOKなんでしょうか?
182 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 16:22:37 ] >>181 template haskell
183 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 16:25:26 ] >>181 ダメ
184 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 16:30:24 ] 2種類の型のどちらかを返したい場合はEitherを使う。 a :: Int -> Either String Int a 1 = Left "hoge" a 2 = Right 2
185 名前:182 mailto:sage [2007/11/17(土) 16:51:52 ] template haskellじゃなくてgeneric haskellだった・・
186 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 22:16:41 ] >>163 今日Haskell始めたばかりのド素人なんだけど、 ones = addlist 1 onesでも、 addlist init xs = init : head xs : tail xs -- [1,1,1,1,1,1,1,1,1,1] addlist init xs = init : xs -- [1,1,1,1,1,1,1,1,1,1] addlist init ~(x:xs) = init : x : xs -- [1,1,1,1,1,1,1,1,1,1] addlist init (x:xs) = init : x : xs -- C stack overflow ってなる。要するに(x:xs)が含まれる部分が先に解釈されるとマズいってことじゃないかな。 単体でのxsはパターンはパターンでも手続き型言語での仮引数と同じ程度の意味しかもたないパターンだから暗黙的に遅延される。 head xsやtail xsも関数だからxsが未確定なら遅延される。 でも(x:xs)というパターンは未確定でも遅延しないでxとxsを照合しようとする。 結果的にinitに値がセットされる前にx:xsを延々と調べ続ける。それではマズいので、(x:xs)を遅延パターンにする、ってことじゃないかな。
187 名前:デフォルトの名無しさん mailto:sage [2007/11/17(土) 23:24:01 ] >>163 明日からHaskell始めるつもりのド素人なんだけど、 関数の仮引数xがconstructor pattern(たとえばy:ys)の場合、 それはcase x of y:ys -> ...という形に変換される。 で、caseの条件式はWHNFまで評価されてしまうので、 遅延させたい時には使えない。
188 名前:186 mailto:sage [2007/11/17(土) 23:31:58 ] >>188 あ、なるほどそういうことなのか。 ありがとう。無理して答えた価値あったわ。
189 名前:163 mailto:sage [2007/11/17(土) 23:59:14 ] なんとなく理解できました。ありがとうございます。 Haskellの考え方に慣れるまでまだ時間がかかりそうですorz
190 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 00:28:05 ] sequence :: Monad m => [m a] -> m [a] sequence = foldr mcons (return []) where mcons p q = p >>= \x -> q >>= \y -> return (x:y) ↑のsequenceの定義を見るとfoldrが使われているんですが、それだと sequence [putStr "foo", putStr "bar"] の場合リストの後ろの方、 つまりputStr "bar"の方が先に評価されるのに、実際には fooの方が先に出力されてしまいます。どうして後ろからではなく、先頭から 評価されるんでしょうか?
191 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 00:55:14 ] 式の評価順とIOモナドの実行順は別物。
192 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 01:04:47 ] sequence [A, B, C] = A `mcons` (B `mcons` (C `mcons` (return []))) = A >>= (\x -> (B `mcons` (C `mcons` (return []))) >>= \y -> return (x:y)) よってA, B, Cの順にエフェクトが出る。
193 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 01:17:35 ] >>178 Haskell今日始めた人なんだけど その最適化の一環としてディスパッチが省略された場合ってのは C++でいうとtemplateによってコード生成された状態と考えていいんですかね
194 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 02:12:23 ] main = putStr "hoge" >>= \x -> putStr "foo" >>= \y -> return x main = putStr "hoge" >>= \x -> putStr "foo" >>= \y -> return y main = putStr "hoge" >>= \x -> putStr "foo" >>= \y -> return "bar" ↑のように最後にreturnさえすればエラーにならずhogefooと出力されるということは、 IOモナドはMaybeモナドやListモナドと違って、最後に何を返すかではなく、 動作をどういう順に行うのかを決めるための仕組みだと考えればいいんでしょうか?
195 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 08:09:29 ] >>193 そんな感じ。 >>194 何を返すかによってmainの型が違う。 上の二例ではIO ()で、最後の例だとIO String。 両方コンパイルが通るのは、mainの型はIO αという形なら何でもよく、 生成されたα型の値は無視されることになってるから。
196 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 13:45:25 ] >>178 実行時にならないとどのインスタンスのコードが実行されるか 静的に決まらない場合ってどんな場合??
197 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 13:51:59 ] >>196 クラスのインスタンス一般に対して書かれた関数は全部そう。例えば、 double :: (Num a) => a -> a double x = x + x こんな関数を定義したら、これをコンパイルする時点ではどの(+)を使うべきか決まらない。
198 名前:193 mailto:sage [2007/11/18(日) 13:56:54 ] >>197 その関数doubleに対して具体的に値を入れたときに コード生成される(静的に生成?)んじゃないんですかね? 頭がC++脳なのでtemplateのことばっかり頭に浮かんでしまうんですがね…
199 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 14:08:31 ] >>198 少なくともGHCやJHCならdoubleが定義されたモジュールをコンパイルする時点でコードを生成する。 そうじゃないと、doubleを使う度に毎回doubleをコンパイルすることになって、 分割コンパイルの恩恵が薄れる。(C++はあえてこれをやってるわけだが) それから、Haskellの仕様上、完全に静的に済ますわけにはいけない。 newtype P a = P a deriving Show nq :: (Show a) => Int -> a -> String nq 0 x = show x nq n x = nq (n-1) (P x) こういう関数をtemplate式でコンパイルしようとしたら、無限にnqのインスタンスを生成する必要がある。 あと、実際にはdoubleのような小さい関数はインライン化されるので、ディスパッチが省略される可能性はある。
200 名前:196 mailto:sage [2007/11/18(日) 14:27:36 ] >>199 なるほど、値(この場合Int)に依存してどういうインスタンスのコードが 実行されるかが決定する場合があるってことか
201 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 14:34:20 ] 1:2:3:[] -> [1,2,3] ↑がこうなるのはわかるんですが 1:2:3 -> ? とやった場合はどんなデータができるんでしょうか?
202 名前:186 mailto:sage [2007/11/18(日) 14:42:10 ] 3はリスト型じゃないからエラーになるんじゃないかな?
203 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 14:43:06 ] あ、名前欄消すの忘れてた……
204 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 14:46:12 ] >>201 (:) :: a -> [a] -> [a]
205 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 14:48:27 ] >>201 やってみりゃいいじゃん。それで挙動に疑問があったらここでもう一度聞いてみな。
206 名前:201 mailto:sage [2007/11/18(日) 15:25:47 ] やってみたんですがテキストに書いてコンパイルしようとするとエラーに なるのにghciで:t 1:2とやると 1:2 :: (Num t, Num [t]) => [t] というなんだかよくわからないメッセージが出ます。 :tだと型チェックしないのかなと思ったんですが :t putStr 1 とやると今度はきちんとエラーが出ます。 ・1:2 :: (Num t, Num [t]) => [t] は一体どういう意味なのか ・なんで:t 1:2はエラーにならないのに:t putStr 1はエラーになるのか ↑2つになる理由は何故なんでしょうか?
207 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 15:43:17 ] >>206 GHCは型クラス周辺を微妙に拡張してるからそのせいだろう。 Haskell98では(Num [t])という文脈はありえない。 Hugsで :t 1:2 と入れたらエラーが出たし。
208 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 15:44:43 ] ghcはIOの実装も特殊なんだよなー
209 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 15:53:43 ] 一応解説。 Haskellでは1とか7とかの整数リテラルは(Num a) => aという型を与えられる。 つまりNumのインスタンスなら何にでもなり得る。具体的にはIntでもIntegerでもRationalでもいいし、 未知のユーザー定義型でもいい。 「1:2」という式では、とりあえず「1」の型をtと書くと、整数リテラルだから(Num t)という制約が必要。 (:)の右辺の型は左辺の型のリストだから、「2」の型は[t]。これも整数リテラルだから制約(Num [t])も要る。 式全体の型は右辺と同じで[t]だから、結果として(Num t, Num [t]) => [t]になる。
210 名前:201 mailto:sage [2007/11/18(日) 16:16:46 ] やっと理解できました。ありがとうございます。
211 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 16:19:47 ] なるほど、どこかで instance Num [Int] のようなことが 書かれていないとも限らない、ということですか。
212 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 16:44:20 ] すいません 初歩的な質問でごめんなさい。 main = do cs <- getContents putStr.unlines $ lines cs これはコンパイル通るんですが main = do cs <- getContents putStr.unlines.lines cs これは通りませんでした…これって何故なんですか? てっきりlinesとunlinesというのは対になってるもんだと思ってたんですが…
213 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 16:50:06 ] putStr.unlines.lines $ cs なら通るよ。 関数適用とか演算子の優先順位の問題だね。 f $ g x == f . g $ x /= f . g x
214 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 16:55:54 ] うろ覚えだが関数抽象より関数適用のほうが優先されるので、 「putStr.unlines.lines cs」の部分が putStr.unlines.(lines cs) って解釈されるはず main = do cs <- getContents (putStr.unlines.lines) cs ならたぶん通る
215 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 16:58:16 ] 二項演算子の周りにはスペースを入れようぜw
216 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 17:00:37 ] C言語で、関数と括弧の間にスペース空ける人?
217 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 17:09:39 ] いや、そこは詰める まあ>>215 をあまり真に受けないでくれ
218 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 17:23:42 ] (.) の周りにはスペースを入れない派なんだが f.g x.h のように関数が引数を持つ場合にやるとなんか微妙
219 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 17:25:16 ] 関数合成が関数適用より優先度低いのが許せない。 こう決めた理由はあるの?
220 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 17:25:37 ] Haskellの解説文を読んでいて、どっかで見たことある書き方だなぁと 思ったら、数学の教科書とソックリです。 つまり、Haskellは数学ができる人向けってことでしょうか?
221 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 17:31:13 ] >>213-214 うお、通りました。ありがとうございます。 関数合成と関数適用の優先順位の問題だったんですね。
222 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 18:15:00 ] >>219 関数適用最強の原則を守るためじゃないか? 俺は現状で満足だ。 map (fromMaybe 0 . fst) xs とか書けるし。
223 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 18:34:32 ] >>219 うざい括弧をつけなくて済む
224 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 20:16:16 ] (f.g) x ↑↑うざい括弧
225 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 20:23:03 ] f.g $ xじゃね?
226 名前:デフォルトの名無しさん mailto:sage [2007/11/18(日) 20:42:38 ] >>224 C言語風には f(g(x)) うざくない?
227 名前:デフォルトの名無しさん mailto:sage [2007/11/19(月) 03:14:41 ] hpcgi2.nifty.com/1to100pen/wiki/wiki.cgi?p=%CB%E8%C6%FCHaskell このページの2007-07-04の日記を参考にプログラムを書いているのですが これで横型探索できる理屈がまったくわかりません
228 名前:デフォルトの名無しさん mailto:sage [2007/11/19(月) 03:39:03 ] Stateモナドについて質問なんですが instance Monad (State s) where m >>= k = State $ \s -> let (a, s') = runState m s in runState (k a) s' ↑の式でm >>= k が m >> kなら、右辺は State $ \s -> let (a, s') = runState m s in runState k s' ((k a)がkだけになる) という風になると考えていいんでしょうか?
229 名前:227 mailto:sage [2007/11/19(月) 04:04:21 ] 227ですが一応目処が立ちました。
230 名前:デフォルトの名無しさん mailto:sage [2007/11/19(月) 04:24:37 ] >>228 それでOK。 ただm >>= kとm >> kのkはそれぞれ別の型だってことに注意。 m1 >> m2 = m1 >>= const m2 なので k=const m2 と考えると runState (k a) s' = runState ((const m2) a) s' = runState m2 s'
231 名前:228 mailto:sage [2007/11/19(月) 10:59:03 ] うーん、難しい >>=が一つだけならなんとか頭で理解できるんですが>>=が二つ以上ならんでいたり do式で表されていたりすると脳味噌が追い付きませんorz
232 名前:143 mailto:sage [2007/11/19(月) 23:12:23 ] *GHC-6.6.1のクロスコンパイルについて公式ページのwikiに書いてない部分* <ターゲット、ホストに共通> デフォルトサーチパスにGNU MPがない場合は--with-gmp-{includes,libraries}で指定する必要があるが、 途中からこの指定(ライブラリサーチパス)を見てくれなくなる上、 できあがったGHCでも-Lオプションを指定しなければいけなくなるので (少なくともlibgmp.so.*かlibgmp.aファイルのどちらかを)デフォルトサーチパスにシンボリックリンクしておくほうがいい。 <ホスト> ghc-6.6.1/Makefileの echo ghc-$(ProjectVersion)/libraries/haskell-src/Language/Haskell/Parser.hs >> hc-files-to-go という行を削除またはコメントアウトする必要がある。 libraries/Cabal/cabal-setup/CabalSetup.hsが作られないので、 cd compiler && make boot && makeの後、 cd libraries/Cabal/cabal-setup rm CabalSetup.{o,hi} cabalsetup ../../../compiler/ghc-inplace -H16m -O -H32m -package Cabal -c CabalSetup.hs -o CabalSetup.o -ohi CabalSetup.hi -keep-hc-files ../../../compiler/ghc-inplace -o cabal-setup -H16m -O -H32m -package Cabal CabalSetup.o する必要がある。 make hc-file-bundle Project=Ghcの前に、 make -C rts AutoApply_thr.hc AutoApply_thr_p.hc AutoApply_debug.hc AutoApply_thr_debug.hc する必要がある。 続く
233 名前:143 mailto:sage [2007/11/19(月) 23:14:33 ] *GHC-6.6.1のクロスコンパイルについて公式ページのwikiに書いてない部分* 続き <ターゲット> いきなり/usr/localにインストールするのではなく、stage1のためのディレクトリにインストールして、 それを利用してもう一度ghcをビルドしたほうがいいと思われる。 *-hc-tar.gzをソースツリーにコピーするのではなく、展開されるghc-6.6.1を手動でソースツリーに上書きする必要がある。 distrib以下のスクリプトに実行権限を与える必要がある。 hc-buildが完了した後、 cd compiler rm -f *.hs-incl make primop-can-fail.hs-incl primop-commutable.hs-incl primop-data-decl.hs-incl primop-has-side-effects.hs-incl primop-list.hs-incl primop-needs-wrapper.hs-inc l primop-out-of-line.hs-incl primop-primop-info.hs-incl primop-strictness.hs-inc l primop-tag.hs-incl primop-usage.hs-incl find . -name \*.o -exec rm {} \; make boot stage=1 && gmake stage=1 cd .. make install stage=1 で完了。 ちなみにザウルスのOpenBSD上では16MB以上のテキストセグメントがある実行ファイルは実行できないので テキストセグメントを32MBに拡張したカーネルを使用しなければビルドできませんでした。 GNU makeがmakeという名前以外(gmakeなど)でインストールされている場合は、適宜読み替えてください。 かなり効率の悪い方法なので、Makefile等をちゃんと読めばもっと最適化できると思います。 古いGHCで新しいGHCをビルドするのはうまくいきますが、 新しいGHCで古いGHCをビルドするのはなかなかうまくいきませんね。
234 名前:デフォルトの名無しさん mailto:sage [2007/11/20(火) 08:39:00 ] 一度評価された式をもう一度評価しようとする場合って、再度最初から評価しなおすんですか? 例えば add x y = x + y という関数があって、一度 add 1 2 という式を評価した後もう一度 add 1 2 を評価しようとするとき、内部では律儀に 1 + 2 を行うんでしょうか?それとも add 1 2 = 3 みたいな式が内部で作られてたりするんでしょうか?
235 名前:デフォルトの名無しさん mailto:sage [2007/11/20(火) 09:30:04 ] ↑の場合は俺も知りたいです 俺が知ってるのは f x a b c = a*x*x + b*x * c という関数に対して f (1+2) 3 4 5 と呼び出した場合に1+2が1度しか評価されないことくらい…
236 名前:デフォルトの名無しさん [2007/11/20(火) 10:20:01 ] >>234 Haskellの規格では規定されてないけど、普通は評価しなおす。 関数を全部メモ化していたら、救いようのないメモリリークが起こるはず。ただし、 map (\x -> x * add 1 2) xs のようなコードが最適化されて let _z = add 1 2 in map (\x -> x * _z) xs になって、add 1 2が一回しか計算されない、という場合はある。