関数型プログラミング言語Haskell Part6
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2006/11/07(火) 21:24:26http://www.haskell.org/
日本語サイト
http://www.sampou.org/cgi-bin/haskell.cgi
http://shidot.dyndns.org/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/
関連スレは>>2
関連書籍は>>3
・2chの仕様により、行頭の半角スペースは表示されません。
コードをインデントしたいときは、代わりに または全角スペースを使うことができます。
0593デフォルトの名無しさん
2007/01/31(水) 16:41:05遅延評価ができなくとも、HaskellのリストをC++のイテレータだと思えば
リスト周りくらいはイテレータ間の変換として作れそうと思ったのです。
-- なんだかboostにありそうな気もするけど
0594デフォルトの名無しさん
2007/01/31(水) 18:56:430595デフォルトの名無しさん
2007/01/31(水) 19:23:54こういうのだろうか。
C++は驚くほどなんでもできるけど、何かしようとするといちいち手間が掛かるし、
細かい言語上の制約がうざったいので、遊び道具にするのも一苦労だ。
0596デフォルトの名無しさん
2007/01/31(水) 20:08:27core2duoのlinux上で試してるんだけど、独立した計算を2つのthreadで同時に
やると、1つずつやるより遅くなってしまう…
main = do
m1 <- newMVar iv
m2 <- newMVar iv
s3 <- takeMVar m1
s4 <- takeMVar m2
t1 <- forkIO (summer m1 80000000)
t2 <- forkIO (summer m2 80000000) -- (1)
s1 <- takeMVar m1 -- (2)
s2 <- takeMVar m2
putStr $ "s1: " ++ (show s1) ++ " s2: " ++ (show s2)
summer m n = if s > 0 then putMVar m s else putMVar m 1
where s = summing n 0 -- summingは0からnまでの和を求める関数
上のcodeだと13秒くらいだが,(1)(2)を入れ替える(つまりthread t1の終了を待ってから
thread t2をはじめる)と、9秒くらいになる。
compile時は-smpをつけて、実行時には+RTS -N2を指定してるんだが…
0597デフォルトの名無しさん
2007/02/01(木) 00:33:30{-# NOINLINE hoge #-} を一杯生成したいんだが
0598596
2007/02/01(木) 19:57:450599デフォルトの名無しさん
2007/02/01(木) 20:06:54キャッシュ汚染のせいだと思う・・・
0600デフォルトの名無しさん
2007/02/01(木) 20:25:58どうもです。
一応summing(0からnまでの和を求める関数)も引数をeagerに評価させて
ほとんどメモリを消費しないようにしてるんだけど…
summing 0 a = a
summing n a | n > 0 && a >= 0 = summing (n-1) (a+n)
これでもキャッシュ汚染は起こりますか?
0601デフォルトの名無しさん
2007/02/01(木) 23:03:28HaskellのライブラリAPIって、ライブラリのソースから自動生成された
(あまり整理されているとは言えない)ドキュメントしかないの?
Network.Socket の使い方が全くわからず数日間悩んでいるのですが‥‥‥。
例えば receipe 集みたいなサイトご存知でしたら教えてください。
本は「ふつうの〜」しか持ってませんが、網羅的な本があったら
がんばって買ってもいいかも。
0602デフォルトの名無しさん
2007/02/01(木) 23:07:530603デフォルトの名無しさん
2007/02/01(木) 23:11:00論文ぐらいしかないよ。
0604デフォルトの名無しさん
2007/02/01(木) 23:30:55それしかない。
Network.Socketについていうと、リファレンスにも書いてあるが、
インタフェースはCのAPIそのままだから、そっちを調べるべき。
関数に説明が付いていないのもこれが理由。
0605デフォルトの名無しさん
2007/02/01(木) 23:33:180606P2Pソフトを妄想中
2007/02/02(金) 00:24:58ありがとう。Cのsocket APIは理解しているつもりなので、想像はできたの
ですが、なんかHaskellicな書き方に慣れないせいか、もうちょっと手引きの
ようなものがあると楽なんですけどね。
なんとかがんばってみます。対向はとりあえずpythonあたりで作って
テスト環境を作ってみないと‥‥‥
0607デフォルトの名無しさん
2007/02/02(金) 17:51:57あの不親切なドキュメントみながら書いてみた
import Network.Socket
main = putStrLn =<< do
sock <- socket AF_INET Stream 0
addr <- inet_addr "66.249.89.104" >>= \x -> return $ SockAddrInet 80 x
connect sock addr
send sock "GET / HTTP/1.1\nHost: www.google.co.jp\n\n"
recv sock 10000000 >>= \x -> sClose sock >> return x
0608デフォルトの名無しさん
2007/02/02(金) 21:19:00ふつうにネットワークのクライアントプログラムを書くだけなら、 Network で充分じゃないかな。
それでは無理な細かいところを調整するために Network.Socket はある。
逆に言うと、そういう細かいところの欲求ってのはCレベルのAPIを叩きたいっ
てことなんだから、関数名と型名だけあれば、まあ充分なんじゃない。
使いづらいし、ちょっとわかりづらいってのは同意だが。
0609デフォルトの名無しさん
2007/02/04(日) 23:36:03代用品は?
0610P2Pソフトを妄想中
2007/02/05(月) 09:39:47ありがとう。こっちも、
http://homepages.paradise.net.nz/warrickg/haskell/http/
っての見付けてきて勉強中です。
>608
UDP使いたいのですが、Networkでできる?
あとIPv6も(って、AF_INET6は定義されているが sockaddr_in6 に対応する
ものが無さげな罠‥‥‥)
0611デフォルトの名無しさん
2007/02/05(月) 10:00:040612デフォルトの名無しさん
2007/02/05(月) 11:52:32詳しく。
0613デフォルトの名無しさん
2007/02/05(月) 12:38:09Haskellじゃなくて、CPUのキャッシュをコンカレントなスレッドが
奪いあったのではないか、という指摘なんじゃないかと。
正直、core2duoのコアとキャッシュの関係を知らないので
そういうことがおこるかどうかは知らない。普通のSMPで、かつ
スケジューラが十分賢ければ、2つactiveなthreadが走ったら
それぞれのthreadをある程度固定化するようにスケジュールして
くれると思うんだけど。
0615デフォルトの名無しさん
2007/02/05(月) 19:28:070616デフォルトの名無しさん
2007/02/05(月) 21:43:29実はsmp対応になってなかっただけ、ってオチがいちばんありそうだな。
0617デフォルトの名無しさん
2007/02/06(火) 00:58:28まだ8bitのバイト列の書き出しすらできねぇ
俺様の頭は激しく悪いな
0618デフォルトの名無しさん
2007/02/06(火) 01:27:51つ[putStr (map toEnum [104,111,103,101])]
つ[import Bits (.&. .|. xor shiftL shiftR)]
0619デフォルトの名無しさん
2007/02/06(火) 01:38:04サンクス! さんざん苦労してこんなん書いてみたが馬鹿みたいだったな(笑)
頭固くなってしまったものだ‥‥‥ orz
class MessageElement a where
encode :: a->String
decode :: String->a
data MEWord8 = MEWord8 Word8 deriving (Show, Eq, Ord)
instance MessageElement MEWord8 where
encode (MEWord8 w8) = [(chr $ fromInteger $ toInteger w8)]
decode = MEWord8 . toEnum . ord . head
0620デフォルトの名無しさん
2007/02/06(火) 09:42:40さぁVBの仕事してくるか・・・
0621デフォルトの名無しさん
2007/02/07(水) 00:37:44Haskell本二冊がどの本屋でも売れ残っているんだが、どっちがおしゅしゅめ?
ちなみに言語はZ80と6800のマシン語しか知らないよ。もう忘れたけど てへ
0622デフォルトの名無しさん
2007/02/07(水) 01:22:250623デフォルトの名無しさん
2007/02/07(水) 01:36:352冊とも内容的に不十分なので、結局は生の論文を読むしかないと思う。
でも、はっきり言ってHaskellは流行らないと思うよ。
関数型言語の理論的なもとになっているラムダ計算自体が古くさい理論になりつつあるからね。
0624デフォルトの名無しさん
2007/02/07(水) 01:39:06データフローとか、今やったらいろいろと面白そうなんだが、
なにせ理論がむつかしい上に自分が手続き型にどっぷり首までつかった
人間なのと、自分の頭が悪いためたいしたことができてない。
0625デフォルトの名無しさん
2007/02/07(水) 01:39:210626デフォルトの名無しさん
2007/02/07(水) 02:14:06Haskellはいまだに嫌いだけどたまに触ってるしこのスレも見てる
0627デフォルトの名無しさん
2007/02/07(水) 02:52:45内容が不十分というのは同意するけど、論文嫁というのは訳分からん。
Haskell 98 Reportを読めば十分だろ。
0628デフォルトの名無しさん
2007/02/07(水) 03:04:45俺Haskell使えますよ? とか言いてぇぇぇぇぇぇぇぇ
0629デフォルトの名無しさん
2007/02/07(水) 08:55:10Haskellがはやらなくてよかった
0630デフォルトの名無しさん
2007/02/07(水) 09:25:590631デフォルトの名無しさん
2007/02/07(水) 09:33:270632デフォルトの名無しさん
2007/02/07(水) 10:29:46そんなことをいったらHaskellとCの違いも微々たるものじゃね?
0633デフォルトの名無しさん
2007/02/07(水) 11:28:300634デフォルトの名無しさん
2007/02/07(水) 11:55:15Haskell98Reportだけでは不十分。
これはC++プログラマがオブジェクト指向の本を読んだりするのと似ている。
0635デフォルトの名無しさん
2007/02/07(水) 12:05:23しかし、λが古くさいって、計算機のパラダイムが根本から変わったなんて話は聞いた事無いんだが…
0636デフォルトの名無しさん
2007/02/07(水) 12:18:09> GHCもHugsも98以降の拡張がガンガン入ってるしねえ。
だね。最近どんどん使われはじめているアローズに付いての記述もないし。
> しかし、λが古くさいって、計算機のパラダイムが根本から変わったなんて話は聞いた事無いんだが…
たとえば、ラムダ計算だけではシームレスにアクションを定義できないし、並列性についても定義できない。
0637デフォルトの名無しさん
2007/02/07(水) 15:56:190638デフォルトの名無しさん
2007/02/07(水) 19:47:39Cにはクロージャが無いからそこに並べるのはちょっとキツい
0639デフォルトの名無しさん
2007/02/07(水) 21:11:320640デフォルトの名無しさん
2007/02/07(水) 21:14:580641デフォルトの名無しさん
2007/02/07(水) 21:46:070642デフォルトの名無しさん
2007/02/07(水) 21:59:540643デフォルトの名無しさん
2007/02/07(水) 22:03:290644デフォルトの名無しさん
2007/02/07(水) 23:30:43>>622-623 返事ありがとう! お礼にボクのちんぽミルクをお口にあ〜ん。
ふつうのHaskell買って見たよ!アホ用に書かれているので読みやすいにゃん
Lispみたいな言語だにゃ。x:xs は Cons CAR CDR だったのかw
忘れてたけど、漏れ昔Lispを勉強したことがあったんだ。
ただし当時ナイコン族だったので脳内Lisp処理系でしか実行したことがないのだがw
うっひょー
0645デフォルトの名無しさん
2007/02/07(水) 23:44:590646デフォルトの名無しさん
2007/02/09(金) 11:07:05そうなの?
0647デフォルトの名無しさん
2007/02/09(金) 13:12:55やぁ お・ま・ん・こんばんわ 昼だけどw
とりあえず8章まではふんふんと来たが代数的データ型でつまづいた。
モナドは難しいことを避けてくれたので何も説明されてないというかw
Newtype宣言したあと『時が見える』見たいな
ところで P199の
(.)関数の型宣言
(.) :: (b−>c) −> (aー>b) −> (a−>c)
凡例 f.g
の順序はこれでいいの隗?
第一引数がgで第二引数がfになるのけ?
0648デフォルトの名無しさん
2007/02/09(金) 13:15:03第一引数がf 第二引数がg
0649デフォルトの名無しさん
2007/02/09(金) 15:25:25結局日本では学生の暇つぶしにしか使われてないのかこの言語。
0650デフォルトの名無しさん
2007/02/09(金) 16:36:24鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥
鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥
鳥鳥烏鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥
鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥
鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥
鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥鳥
烏を探せ
0651デフォルトの名無しさん
2007/02/09(金) 20:45:33鳥鳥鳥
鳥鳥鳥
鳥鳥烏
0652デフォルトの名無しさん
2007/02/10(土) 00:08:021秒かからず気づいた俺は天才?
ところで、Javaしかできない低脳初級プログラマなんだけど
『高階関数』について、よくわからないんだ
引数に関数を利用するのが高階関数って考えるのは簡単なことだけど、
例えばJavaだって、引数にメソッドを利用することは可能だよね
class A {
private int value ; //属性
public int getNum() { //メソッド1
return 100;
}
public void setValue( int i ) { //メソッド2
value = i ;
}
public static void main( String args[] ) { //mainメソッド
setValue( getNum() ) ;
System.out.println( value ) ;
}
}
でも、Javaには高階関数なんてないわけだよね?
上に書いたclassAは、setValue( int i )の定義で、引数の中にメソッドを入れることは不可能
それと違ってHaskellは、関数の定義(型の宣言)で引数に関数を入れれる
これが高階関数?
でも結局のところ、Haskellの関数は値になるわけだから、
Javaのメソッドの引数に、メソッド入れるのと何が違うのよって・・・(???)
0653デフォルトの名無しさん
2007/02/10(土) 00:23:20たとえば、こういうのはできるかな?
hoge :: Int -> Int -> Int
hoge a b = a + b
hoge2 :: (Int -> Int) -> Int -> Int
hoge2 a b = a b
hoge3 :: Int
hoge3 = hoge2 (hoge 1) 3
0654デフォルトの名無しさん
2007/02/10(土) 01:17:28関数を引数にするのはまあいいんだけど、
関数を返す関数も高階関数になる。
0655デフォルトの名無しさん
2007/02/10(土) 01:24:01新しいJavaの仕様でクロージャを導入したらしいけど
0656デフォルトの名無しさん
2007/02/10(土) 01:28:31ttp://journal.mycom.co.jp/articles/2006/08/23/java7closuer/004.html
0657デフォルトの名無しさん
2007/02/10(土) 01:35:12とりあえずやってみる
classは省略
class X {
public int hoge( int a, int b ) {
return a + b ;
}
}
できた。
class Y {
public int hoge2( ) {
//abってa*bのこと?
}
}
わからん。
class Z {
public int hoge3(???){}
}
さっぱりわからん
先生わかりません
>>655
去年の12月にJava6がでたばっか
Java7はまだまだ先
クロージャについても、まだ検討段階のはずだけど
0658デフォルトの名無しさん
2007/02/10(土) 02:20:33と思えばだいたい OK。
hoge3 を計算すると次のようになる。
hoge3
= hoge2 (hoge 1) 3 (def. of hoge3)
= (hoge 1) 3 (def. of hoge2)
= 1 + 3 (def. of hoge)
= 4
0659デフォルトの名無しさん
2007/02/10(土) 02:31:56ここは
= hoge (1 3) (def. of hoge2)
のほうがわかりやすいな
0660デフォルトの名無しさん
2007/02/10(土) 02:56:33hoge (1 3) は hoge という関数に (1 3) という値を食わせることに
なるが、(1 3) という値が意味不明なので、正しく評価できない。
0661デフォルトの名無しさん
2007/02/10(土) 03:28:01public void setValue( int i ) {
これ、自分で引数にint iって書いてあるように、
実際に渡されているのは、関数じゃなくて返り値のintだお。
0662デフォルトの名無しさん
2007/02/10(土) 07:40:23これからJavaを新しく学ぼうとする奴は大変だな。
C++でもJavaでも、流行り出した頃に始めると
情報多いし似たようなことやってる人も多いし学習曲線もなだらかで
その後も放っておいても情報が入ってくるけど、
ある程度成熟してからはじめて勉強するのって大変よね。
0663デフォルトの名無しさん
2007/02/10(土) 14:52:11Haskellは興味を持ったばかりで全く読み取れないですが
こんな感じでよろしいでしょうか?
interface A { int f(int a, int b); }
class B { A a; int b;
B(A a, int b) { this.a = a; this.b = b; }
int f(int n) { return a.f(b, n); }
}
public class C {
static int hoge2(B b, int n) { return b.f(n); }
public static void main(String args[]) {
A hoge = new A() {
public int f(int a, int b) { return a + b; }};
B hoge1 = new B(hoge, 1);
int hoge3 = hoge2(hoge1, 3);
System.out.println(hoge3);
}
}
スレ違いっぽくてすみません。
0664デフォルトの名無しさん
2007/02/10(土) 15:41:55違う言語だから同じかどうかはっきりとは言えないわけだけど、
意図している記法とは違うと思うよ。
最終的な出力は同じでもね。
0665デフォルトの名無しさん
2007/02/10(土) 15:53:03Aを二引数の関数、Bを一引数の関数と見ればかなり良く対応していると思うが。
0666デフォルトの名無しさん
2007/02/10(土) 16:23:09それはカリー化ではない
0667デフォルトの名無しさん
2007/02/10(土) 16:34:29何が言いたいのか分からん。
>>653は高階関数と部分適用の実演であって、Haskellでは部分適用を
カリー化を利用して行うのが一般的だからそうしているに過ぎないと思ったが。
その気になれば>>663をカリー化された形に書き換えられるだろうが、
それに何か意義があるのか?
0668デフォルトの名無しさん
2007/02/10(土) 17:01:53記法はともかく雰囲気があっているか(理解が正しいかどうか)
確かめたかっただけです。
Bのfをinterfaceにしてimplementsすればよりそれっぽかったかな。
0669667
2007/02/10(土) 17:55:44感情的な攻撃をしたつもりはなかった。
そう見えたのなら謝る。投稿内容は無視してほしい。
0670668
2007/02/10(土) 18:41:28書き忘れていましたが 663=668≠652 です。
あとhoge2の型も作らないといけなかったですかね。
0671デフォルトの名無しさん
2007/02/10(土) 19:37:18> その気になれば>>663をカリー化された形に書き換えられるだろうが
Haskellで書かれたコードをJavaで模倣したいのかと思ったんだが、
もしそうなら当然模倣できるところは全部模倣すべきだよ。
0672デフォルトの名無しさん
2007/02/10(土) 20:53:090673デフォルトの名無しさん
2007/02/10(土) 21:22:01public class Main {
public static void main(String[] args) {
System.out.println("hoge3 = " + (Integer)new Hoge3().reduce());
}
}
abstract class Closure {
Stack args;
Closure() { args = new Stack(); }
Closure apply(Object o) { args.push(o); return this; }
abstract Object reduce();
}
class Hoge extends Closure {
Object reduce() { return (Integer)args.get(0) + (Integer)args.get(1); }
}
class Hoge2 extends Closure {
Object reduce() { return ((Closure)args.get(0)).apply(args.get(1)).reduce(); }
}
class Hoge3 extends Closure {
Object reduce() { return new Hoge2().apply(new Hoge().apply(1)).apply(3).reduce(); }
}
0674デフォルトの名無しさん
2007/02/10(土) 21:28:540675デフォルトの名無しさん
2007/02/10(土) 23:10:33苦労しながらsin x のテイラー展開の収束性を見るプログラムを書いたw
引数は展開次数nとxなのだが、そのうちの展開次数nだけを[1..10]にマップしたい。
だがその方法が分からんので優しいお方おすえて。
カリーかとやらで第一引数だけをまず展開するんじゃないかと思ったが、うまくいかない。
どこを勘違いしているのかも含めてvipperにも分かるように3行で教えてくれw
module Main (main) where
-- Taylor expansion / Honer's method
sin'' 0 x y = y
sin'' n x y = sin'' (n - 1) x ( 1.0 - x * y / ( (2 * n + 1) * (2 * n) ) )
sin' n x = x * sin'' n (x * x) 1.0
converge_sin n = sin' n 1.0
main = print $ map converge_sin [1..10]
出力
[0.8333333333333334,0.8416666666666667,0.841468253968254,0.8414710097001764,0.84
1470984648068,0.8414709848086585,0.8414709848078937,0.8414709848078965,0.8414709
848078965,0.8414709848078965]
じゃわカリー/~
0676デフォルトの名無しさん
2007/02/10(土) 23:27:56それでできてるじゃないか。何が不満?
0677デフォルトの名無しさん
2007/02/11(日) 00:10:04converge_sin n という捨て関数を使っているし、角度の引数xはこの中で固定化されている。
それが不満。
Mapすると同時に、角度xもパラメータとして与えたい。
0678デフォルトの名無しさん
2007/02/11(日) 00:16:49main = print $ map (flip sin' 1) [1..10]
main = print $ map (`sin'` 1) [1..10]
main = print $ map f [1..10]
where
f n = sin' n 1
好きなのをどうぞ。
0679デフォルトの名無しさん
2007/02/11(日) 00:39:28こんな感じか?
module Main (main) where
-- Taylor expansion / Honer's method
sin'' 0 x y = y
sin'' n x y = sin'' (n - 1) x ( 1.0 - x * y / ( (2 * n + 1) * (2 * n) ) )
sin' n x = x * sin'' n (x * x) 1.0
main = print $ (\x -> map (\n -> sin' n x) [1..10] ) 1.0
0680デフォルトの名無しさん
2007/02/11(日) 23:30:38手続き型に20年安住してしまったので頭固すぎて挫折しそうですパパ。
0681ちっとも理解が進まねぇorz
2007/02/11(日) 23:40:59サーバを作るときって、次のどちらが素直な設計になるますか?
ヒント頂けると有り難く。
a: State に全部の通信の状態をくるんでしまい、非同期にkeepaliveする
recvfromあるいはselectでタイムアウト付きのwaitがしたくなる、
が、探しかたが悪いのかやりかたがよくわからない‥‥‥。
b: マルチスレッドで走らせてがんばる
>596のforkIOってオイシイ?
スレッド間での状態の同期ってできるの?
c: そもそもそういう処理をHaskellでやろうと思う方が無茶
d: 俺が馬鹿なだけで、もっと簡単な方法がある
0682ちっとも理解が進まねぇorz
2007/02/12(月) 00:19:26まだレベル1と2の間にの俺にはよくわからない気がするが、明日よんでみよう。
STMってなんじゃらほい。interopの小間使いか(ぉぃ)
0683デフォルトの名無しさん
2007/02/12(月) 09:14:29サブディレクトリの中身も取得するgetDirectoryContentsを書いたのだが
どうもコードに無駄があるように思える。
Haskellらしく簡潔に書くにはどう書いたらいいんだ?
--
module GetRecursiveContents (getRecursiveContents) where
import System.Directory
import Data.List
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents p = do cs <- getDirectoryContents p
result <- mapM (getRecursiveContents' p) $ filter (not . isSuffixOf ".") cs
return $ concat result
getRecursiveContents' :: FilePath -> FilePath -> IO [FilePath]
getRecursiveContents' p c = do let newPath = mergePath p c
dir <- doesDirectoryExist newPath
if dir then getRecursiveContents newPath
else return [newPath]
mergePath :: FilePath -> String -> FilePath
mergePath a b
| "\\" `isSuffixOf` a = a ++ b
| otherwise = a ++ "\\" ++ b
0684デフォルトの名無しさん
2007/02/12(月) 09:43:53bだろ。
同期を取るには二つ方法があって、MVarという古典的な共有変数を使っても良いし、
STMという仕組みでロックなしに共有状態を操作しても良い。
STMはちゃんと使ったことがないけど、たぶん次のような特徴がある。
・MVarでできることはなんでもできる。
・明示的にロックをエミュレートしたりしない限り、デッドロックを気にする必要がない。
・(どの程度か知らないが)遅い。
詳しくは、リファレンスや、そこからたどれる論文を読んでくれ。
0685デフォルトの名無しさん
2007/02/12(月) 12:24:50再帰の深さの指定をつける時を考えると、ツリー構造定義する方が早い気がする
import Monad
dirrec :: FilePath -> IO [FilePath]
dirrec p = do
cs <- getDirectoryContents p
let paths = [ p' ++ c | c <- cs, not ("." `isSuffixOf` c) ]
dirps <- mapM doesDirectoryExist paths
zipWithM dive dirps paths
where
p' = addYen p
where
addYen "\\" = "\\"
addYen [c] = c : "\\"
addYen (c:cs) = c : addYen cs
dive False = return
dive True = fmap concat . dirrec
0686685
2007/02/12(月) 12:47:59型が合っても動作が違う
(...)
fmap concat $ zipWithM dive dirps paths
(...)
where
dive False p = return [p]
dive True p = dirrec p
0687デフォルトの名無しさん
2007/02/12(月) 13:04:43getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents fp
= getDirectoryContents fp >>= mapM (fx fp) >>= return . concat
where
fx :: FilePath -> FilePath -> IO [FilePath]
fx bp "." = return [bp]
fx bp ".." = return []
fx bp f = do let np = bp ++ ('/':f)
b <- doesDirectoryExist np
if b then getRecursiveContents np
else return [np]
0688ちっとも理解が進まねぇorz
2007/02/12(月) 14:27:04ありがと。
どうせ同期を取るのは数秒に一回〜1秒に数回程度で、別に遅くてもいいから
STM使ってみるよ。ghc6.2では使えないんだよね。
0689デフォルトの名無しさん
2007/02/12(月) 14:28:38getRecursiveContents fp = liftM concat $ mapM f =<< getDirectoryContents fp
where
f "." = return []
f ".." = return []
f name = getRecursiveContents path `catch` \e -> return [path]
where
path = fp ++ "/" ++ name
doesDirectoryExistが気持ち悪かったので書き直してみたが、
今度は例外を握りつぶしていて良くない。
「inappropriate type」だけ選択的にcatchするにはどうすれば良いんだろう。
0690デフォルトの名無しさん
2007/02/12(月) 21:47:250691683
2007/02/12(月) 22:38:10がんばってソース読んでみる。
「あるディレクトリ以下の全てのログファイル
(拡張子固定)をすべて集計」ってのをやりたかったんだが
意外とめんどいコードが要るのな。
0692デフォルトの名無しさん
2007/02/12(月) 23:35:19■ このスレッドは過去ログ倉庫に格納されています