関数型プログラミング言語Haskell Part8
- 1 :デフォルトの名無しさん:2007/10/30(火) 20:28:13
- haskell.org
http://www.haskell.org/
日本語サイト
http://www.sampou.org/cgi-bin/haskell.cgi
http://www.shido.info/hs/
過去ログ
関数型プログラミング言語Haskell
Part1 http://pc.2ch.net/tech/kako/996/996131288.html
Part2 http://pc2.2ch.net/test/read.cgi/tech/1013846140/
Part3 http://pc8.2ch.net/test/read.cgi/tech/1076418993/
Part4 http://pc8.2ch.net/test/read.cgi/tech/1140717775/
Part5 http://pc8.2ch.net/test/read.cgi/tech/1149263630/
Part6 http://pc11.2ch.net/test/read.cgi/tech/1162902266/
Part7 http://pc11.2ch.net/test/read.cgi/tech/1174211797/
・2chの仕様により、行頭の半角スペースは表示されません。
コードをインデントしたいときは、代わりに または全角スペースを使うことができます。
- 143 :デフォルトの名無しさん:2007/11/14(水) 22:55:19
- ここってクロスコンパイルネタはスレ違いですか?
- 144 :デフォルトの名無しさん:2007/11/14(水) 23:11:31
- ここしかないだろw
- 145 :デフォルトの名無しさん:2007/11/14(水) 23:31:03
- クロスコンパイルの場合、GHC(6.4.xや6.6.x)のMakefileって修正なしで通りますか?
依存関係を無視したり、更新情報を無視したり、
無いファイルを参照したり、必要なターゲットを生成しなかったりと
明らかに修正しなければならない部分が多々あるようですが
- 146 :143=145: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:2007/11/15(木) 00:07:35
- ちなみにOpenBSD-makeではなくGNU-makeを使用しています
- 148 :デフォルトの名無しさん:2007/11/15(木) 01:19:56
- Ubuntu上のemacs22+ghc6-6.1でHaskellのプログラムを色々試しているんですが
C-c, C-lを実行するとよくEmacsが固まってしまって何の入力も受け付けなく
なってしまいます。そのたびにkill -KILLをしているんですが
同じような症状の人はいないでしょうか?
- 149 :デフォルトの名無しさん:2007/11/15(木) 01:36:11
- debianですが、固まりませんね。
- 150 :デフォルトの名無しさん:2007/11/15(木) 03:01:07
- IORefについて質問です。
do ioref <- newIORef 0
modifyIORef ioref (+1)
readIORef ioref >>= print
という式の中でmodifyIORef ioref (+1)がiorefの値を変更している仕組みが
どうしてもわかりません。予想としては
・modifyIORefを使うと引数の値を変更できると言語の根っこの部分で決められている
という事かなと思っているんですが、この考えでいいんでしょうか?
- 151 :デフォルトの名無しさん: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:2007/11/15(木) 08:04:34
- >>151
つまりHaskellは、定数だけでなく、変更される変数の値を保存しておくための(つまり再代入可能な)
場所も用意しているということなんでしょうか?
- 153 :デフォルトの名無しさん:2007/11/15(木) 10:27:06
- >>152
実装上はその通り。GHCにはヒープ上に変更可能オブジェクトを置くための機構があるし、
多分Hugsも似たようなもの。
一方で、言語について「Haskellは〜用意している」という言い方をするのは誤解がある気がする。
実際、>>151の言うように、IORefを使っても(Haskellの普通の)変数の値が変更されることはないし、
言語の根幹に変更を迫るような拡張じゃない。
扱える型を限定すれば、自分で(ファイル入出力を使ったりして)IORefみたいなものを書くこともできる。
- 154 :150:2007/11/15(木) 13:37:19
- >>153
よくわかりました。ありがとうございます。
今入門HaskellとふつうのHaskellの二冊を読みながら色々試しているんですが
もうちょっと詳しい説明が欲しいなと思うことがよくあります。
そこでプログラミングPerlのような
・どのようにHaskellでプログラミングするか
・Haskellはどういう理由でこういう風になっているのか
を解説した本が欲しいのですが、テンプレに載っている洋書で↑の内容に
合っている本はないでしょうか?
- 155 :143: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 :デフォルトの名無しさん:2007/11/15(木) 13:56:24
- >>154
・どのようにHaskellでプログラミングするか
→『Haskell: The Craft of Functional Programming』
・Haskellはどういう理由でこういう風になっているのか
→『Introduction to Functional Programming Using Haskell』
かなあ。両方とも良い本だと思う。まだ全部読み切ってないけど。
- 157 :150:2007/11/15(木) 21:41:29
- >>156
その二冊ですね。お金に余裕ができたら買ってみます。
話は変わるのですがHaskellのガベージコレクションは他の言語(java,ruby...)
と比べて動作する機会がほとんどないと思うんですがどうでしょうか。
変数の宣言時にしか値を入れられなくて、グローバル変数とスタック上に
載せられるローカル変数でほとんど全てが賄えるなら
どこからも参照されていないデータ(ガベージコレクタの対象になるデータ)
ができるなんてことはまずないと思うんですが・・・
- 158 :デフォルトの名無しさん:2007/11/15(木) 22:41:43
- >>157
そんなことはない。遅延評価のために何でもかんでもヒープに割り当てないといけないので、
Haskellは平均的な言語よりずっと多くゴミを出す。
GHCでコンパイルしたプログラムなら、+RTS -Sstderrオプションをつけて実行すれば
GCがどれくらい動いたかが分かる。
適当なプログラムで試してみたけど、約3秒の実行時間中にヒープから700MBほど確保し、
そのうち約9割は第0世代のGCで即座に捨てられてた。
- 159 :デフォルトの名無しさん:2007/11/15(木) 22:45:57
- 具体的に数字出されるとびっくりするなw
- 160 :デフォルトの名無しさん:2007/11/15(木) 22:47:23
- 俺もびっくりしたwww
- 161 :デフォルトの名無しさん:2007/11/15(木) 23:07:27
- 700MB?
700mBの間違いじゃないのか
- 162 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2007/11/16(金) 01:10:19
- やさしい Haskell 入門を今見ているんですが
4.4 遅延パターン
http://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 :デフォルトの名無しさん:2007/11/16(金) 02:19:04
- >>162
これって瞬間最大メモリ使用量が700MBってこと?
- 165 :デフォルトの名無しさん:2007/11/16(金) 02:50:58
- うさのパソコンはメモリ256MB!
- 166 :デフォルトの名無しさん:2007/11/16(金) 02:52:24
- アプリ側がメモリ確保に成功しても、
OS側で本当に実メモリを消費したとは限らないから
調べないと分からないか。
- 167 :デフォルトの名無しさん:2007/11/16(金) 03:27:46
- >>164
アロケートされたメモリの数が700MBってことなのだが、実際はgeneration 0に割り当てられた少ないメモリが使いまわされているだけだから、メモリの使用量自体は少ないはず。
- 168 :デフォルトの名無しさん:2007/11/16(金) 07:15:29
- >>164
OSから確保したのが32MB
実際のヒープオブジェクトの総量が瞬間最大で13,955,072 bytes
コピーGCだからOSから確保した領域の半分以下しか貯められない
- 169 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2007/11/16(金) 18:08:04
- unsafe禁止令
- 171 :デフォルトの名無しさん:2007/11/16(金) 18:26:23
- xs <- sequence $ replicate 3 $ interleaveState get
の間違いか?
どっちにしても無理だろ
- 172 :デフォルトの名無しさん:2007/11/16(金) 18:36:40
- >>171
すいません、間違いでした
無理orz
- 173 :デフォルトの名無しさん:2007/11/16(金) 22:22:17
- モナドと代数的データ型に的を絞って詳しく扱ってるテキストはないでしょうか
- 174 :デフォルトの名無しさん:2007/11/17(土) 03:16:48
- foo >>= bar
としたときに実際に>>=がどのインスタンスに定義されている>>=の処理を行うのか、
というのはどうやって決まるんでしょうか?
- 175 :デフォルトの名無しさん:2007/11/17(土) 07:11:03
- >>174
型推論。fooの型とbarの型とその式の使われ方が勘案される。
- 176 :デフォルトの名無しさん:2007/11/17(土) 11:11:46
- >>175
それはコンパイル時と実行時のどちらでされるものなんでしょうか?
- 177 :デフォルトの名無しさん:2007/11/17(土) 11:43:58
- >>176
実行時
- 178 :デフォルトの名無しさん:2007/11/17(土) 11:57:24
- ・型推論自体はコンパイル時。
・ただし、型クラスのディスパッチは実行時まで遅延される。
・ただし、どのインスタンスについてのコードを生成すれば良いか静的に決まる場合は、
最適化の一環としてディスパッチを省略する。
こんな感じか。
- 179 :174: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 :デフォルトの名無しさん:2007/11/17(土) 13:28:59
- >>179
途中まで読んだだけだけどコンビネータの話。
S,K,I とか。Yコンビネータも出てきたかは覚えてない。
- 181 :デフォルトの名無しさん:2007/11/17(土) 16:07:56
- a 1 = "hoge"
a 2 = 2
のような引数によって異なる型の値を返すことはOKなんでしょうか?
- 182 :デフォルトの名無しさん:2007/11/17(土) 16:22:37
- >>181
template haskell
- 183 :デフォルトの名無しさん:2007/11/17(土) 16:25:26
- >>181
ダメ
- 184 :デフォルトの名無しさん:2007/11/17(土) 16:30:24
- 2種類の型のどちらかを返したい場合はEitherを使う。
a :: Int -> Either String Int
a 1 = Left "hoge"
a 2 = Right 2
- 185 :182:2007/11/17(土) 16:51:52
- template haskellじゃなくてgeneric haskellだった・・
- 186 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2007/11/17(土) 23:24:01
- >>163
明日からHaskell始めるつもりのド素人なんだけど、
関数の仮引数xがconstructor pattern(たとえばy:ys)の場合、
それはcase x of y:ys -> ...という形に変換される。
で、caseの条件式はWHNFまで評価されてしまうので、
遅延させたい時には使えない。
- 188 :186:2007/11/17(土) 23:31:58
- >>188
あ、なるほどそういうことなのか。
ありがとう。無理して答えた価値あったわ。
- 189 :163:2007/11/17(土) 23:59:14
- なんとなく理解できました。ありがとうございます。
Haskellの考え方に慣れるまでまだ時間がかかりそうですorz
- 190 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2007/11/18(日) 00:55:14
- 式の評価順とIOモナドの実行順は別物。
- 192 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2007/11/18(日) 01:17:35
- >>178
Haskell今日始めた人なんだけど
その最適化の一環としてディスパッチが省略された場合ってのは
C++でいうとtemplateによってコード生成された状態と考えていいんですかね
- 194 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2007/11/18(日) 08:09:29
- >>193
そんな感じ。
>>194
何を返すかによってmainの型が違う。
上の二例ではIO ()で、最後の例だとIO String。
両方コンパイルが通るのは、mainの型はIO αという形なら何でもよく、
生成されたα型の値は無視されることになってるから。
- 196 :デフォルトの名無しさん:2007/11/18(日) 13:45:25
- >>178
実行時にならないとどのインスタンスのコードが実行されるか
静的に決まらない場合ってどんな場合??
- 197 :デフォルトの名無しさん:2007/11/18(日) 13:51:59
- >>196
クラスのインスタンス一般に対して書かれた関数は全部そう。例えば、
double :: (Num a) => a -> a
double x = x + x
こんな関数を定義したら、これをコンパイルする時点ではどの(+)を使うべきか決まらない。
- 198 :193:2007/11/18(日) 13:56:54
- >>197
その関数doubleに対して具体的に値を入れたときに
コード生成される(静的に生成?)んじゃないんですかね?
頭がC++脳なのでtemplateのことばっかり頭に浮かんでしまうんですがね…
- 199 :デフォルトの名無しさん: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:2007/11/18(日) 14:27:36
- >>199
なるほど、値(この場合Int)に依存してどういうインスタンスのコードが
実行されるかが決定する場合があるってことか
- 201 :デフォルトの名無しさん:2007/11/18(日) 14:34:20
- 1:2:3:[] -> [1,2,3]
↑がこうなるのはわかるんですが
1:2:3 -> ?
とやった場合はどんなデータができるんでしょうか?
- 202 :186:2007/11/18(日) 14:42:10
- 3はリスト型じゃないからエラーになるんじゃないかな?
- 203 :デフォルトの名無しさん:2007/11/18(日) 14:43:06
- あ、名前欄消すの忘れてた……
- 204 :デフォルトの名無しさん:2007/11/18(日) 14:46:12
- >>201
(:) :: a -> [a] -> [a]
- 205 :デフォルトの名無しさん:2007/11/18(日) 14:48:27
- >>201
やってみりゃいいじゃん。それで挙動に疑問があったらここでもう一度聞いてみな。
- 206 :201: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 :デフォルトの名無しさん:2007/11/18(日) 15:43:17
- >>206
GHCは型クラス周辺を微妙に拡張してるからそのせいだろう。
Haskell98では(Num [t])という文脈はありえない。
Hugsで :t 1:2 と入れたらエラーが出たし。
- 208 :デフォルトの名無しさん:2007/11/18(日) 15:44:43
- ghcはIOの実装も特殊なんだよなー
- 209 :デフォルトの名無しさん: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:2007/11/18(日) 16:16:46
- やっと理解できました。ありがとうございます。
- 211 :デフォルトの名無しさん:2007/11/18(日) 16:19:47
- なるほど、どこかで instance Num [Int] のようなことが
書かれていないとも限らない、ということですか。
- 212 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2007/11/18(日) 16:50:06
- putStr.unlines.lines $ cs
なら通るよ。
関数適用とか演算子の優先順位の問題だね。
f $ g x == f . g $ x /= f . g x
- 214 :デフォルトの名無しさん:2007/11/18(日) 16:55:54
- うろ覚えだが関数抽象より関数適用のほうが優先されるので、
「putStr.unlines.lines cs」の部分が
putStr.unlines.(lines cs)
って解釈されるはず
main = do
cs <- getContents
(putStr.unlines.lines) cs
ならたぶん通る
- 215 :デフォルトの名無しさん:2007/11/18(日) 16:58:16
- 二項演算子の周りにはスペースを入れようぜw
- 216 :デフォルトの名無しさん:2007/11/18(日) 17:00:37
- C言語で、関数と括弧の間にスペース空ける人?
- 217 :デフォルトの名無しさん:2007/11/18(日) 17:09:39
- いや、そこは詰める
まあ>>215をあまり真に受けないでくれ
- 218 :デフォルトの名無しさん:2007/11/18(日) 17:23:42
- (.) の周りにはスペースを入れない派なんだが
f.g x.h のように関数が引数を持つ場合にやるとなんか微妙
- 219 :デフォルトの名無しさん:2007/11/18(日) 17:25:16
- 関数合成が関数適用より優先度低いのが許せない。
こう決めた理由はあるの?
- 220 :デフォルトの名無しさん:2007/11/18(日) 17:25:37
- Haskellの解説文を読んでいて、どっかで見たことある書き方だなぁと
思ったら、数学の教科書とソックリです。
つまり、Haskellは数学ができる人向けってことでしょうか?
- 221 :デフォルトの名無しさん:2007/11/18(日) 17:31:13
- >>213-214
うお、通りました。ありがとうございます。
関数合成と関数適用の優先順位の問題だったんですね。
- 222 :デフォルトの名無しさん:2007/11/18(日) 18:15:00
- >>219
関数適用最強の原則を守るためじゃないか?
俺は現状で満足だ。
map (fromMaybe 0 . fst) xs
とか書けるし。
- 223 :デフォルトの名無しさん:2007/11/18(日) 18:34:32
- >>219
うざい括弧をつけなくて済む
- 224 :デフォルトの名無しさん:2007/11/18(日) 20:16:16
- (f.g) x
↑↑うざい括弧
- 225 :デフォルトの名無しさん:2007/11/18(日) 20:23:03
- f.g $ xじゃね?
- 226 :デフォルトの名無しさん:2007/11/18(日) 20:42:38
- >>224
C言語風には f(g(x))
うざくない?
- 227 :デフォルトの名無しさん:2007/11/19(月) 03:14:41
- http://hpcgi2.nifty.com/1to100pen/wiki/wiki.cgi?p=%CB%E8%C6%FCHaskell
このページの2007-07-04の日記を参考にプログラムを書いているのですが
これで横型探索できる理屈がまったくわかりません
- 228 :デフォルトの名無しさん: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:2007/11/19(月) 04:04:21
- 227ですが一応目処が立ちました。
- 230 :デフォルトの名無しさん: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:2007/11/19(月) 10:59:03
- うーん、難しい
>>=が一つだけならなんとか頭で理解できるんですが>>=が二つ以上ならんでいたり
do式で表されていたりすると脳味噌が追い付きませんorz
- 232 :143: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: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をビルドするのはなかなかうまくいきませんね。
141 KB
[ 2ちゃんねる 3億PV/日をささえる レンタルサーバー \877/2TB/100Mbps]
■ おすすめ2ちゃんねる 開発中。。。 by FOX ★
このスレを見ている人はこんなスレも見ています。(ver 0.20)
圏論 / カテゴリー論 / Category Theory 3 [数学]
過去ログ [情報学]
新着レスの表示
掲示板に戻る
全部
前100
次100
最新50
read.cgi ver 05.0.4.9 2007/06/21
FOX ★ DSO(Dynamic Shared Object)