関数型プログラミング言語Haskell Part19
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2012/06/27(水) 10:21:10.18ttp://www.haskell.org/
日本語サイト
ttp://www.sampou.org/cgi-bin/haskell.cgi
ttp://www.shido.info/hs/
過去ログ
関数型プログラミング言語Haskell
Part1 ttp://pc.2ch.net/tech/kako/996/996131288.html
Part2 ttp://pc2.2ch.net/test/read.cgi/tech/1013846140/
Part3 ttp://pc8.2ch.net/test/read.cgi/tech/1076418993/
Part4 ttp://pc8.2ch.net/test/read.cgi/tech/1140717775/
Part5 ttp://pc8.2ch.net/test/read.cgi/tech/1149263630/
Part6 ttp://pc11.2ch.net/test/read.cgi/tech/1162902266/
Part7 ttp://pc11.2ch.net/test/read.cgi/tech/1174211797/
Part8 ttp://pc11.2ch.net/test/read.cgi/tech/1193743693/
Part9 ttp://pc11.2ch.net/test/read.cgi/tech/1211010089/
Part10 ttp://pc12.2ch.net/test/read.cgi/tech/1231861873/
Part11 ttp://pc12.2ch.net/test/read.cgi/tech/1252382593/
Part12 ttp://hibari.2ch.net/test/read.cgi/tech/1272536128/
Part13 ttp://hibari.2ch.net/test/read.cgi/tech/1286706874/
Part14 ttp://hibari.2ch.net/test/read.cgi/tech/1299385928/
Part15 ttp://hibari.2ch.net/test/read.cgi/tech/1310199414/
Part16 ttp://toro.2ch.net/test/read.cgi/tech/1317958045/
Part17 ttp://toro.2ch.net/test/read.cgi/tech/1325510368/
Part18 ttp://toro.2ch.net/test/read.cgi/tech/1331902463/
0263デフォルトの名無しさん
2012/07/15(日) 19:58:59.40でも雰囲気は分ってもらえると思う。
0264248
2012/07/15(日) 20:23:42.91使ってみた方はいるでしょうか。
パフォーマンスはどれほど出るものなのでしょうか。
このパッケージの github にあるサンプルコードを見てみると、
こちらは自分で OpenCL のコードを書かなければならないみたいですが、
DSL タイプの支援ライブラリは無いのでしょうか。
0265デフォルトの名無しさん
2012/07/15(日) 21:37:54.99いろいろ試しているけど、
あなたが今使っているコードがどういうものか分からないので、
比較ができないぁ
あなたがいま実際に取り組んでいる実際の問題でなくても構わないので、
高速化をしたら比較できるような対象となるお題コードを、
http://ideone.com/ とかにアップしてURIを張り付けてよ
0266デフォルトの名無しさん
2012/07/15(日) 22:21:35.02monadiusの作り方
0267237
2012/07/15(日) 23:00:10.71http://ideone.com/l7Ina に私のコードを貼り付けました。
そのまま ghci でロードして頂ければサンプルデータで実行できます。
任意長の元データ b とカーネルデータ k (|b| >= |k|)に対して、
>>237 のような演算を行う関数 calc を定義しています。
このコードの (\i -> kp (Z:.i) * bp (Z:.ic+i)) の辺りが何とも間の抜けた感じです。
配列に対してインデックスで要素単体を指定して演算しているのが、
なんていうか Haskell らしくないというか、気持ちが落ち着かないというか・・・
traverse 系関数ではこういうインデックス指定に対して特に最適化して作られていて、
この方法が最も効率がいいというのなら仕方ありませんが、
もっと効率よくて見やすいコードになるのなら嬉しいです。
ちなみに >>237 のような演算は、同じカーネルを対角線に階段状に並べたN重対角行列と、
元データのベクトルとの積の演算なので、hmatrix でやった方が速いかも知れませんね。
明日 hmatrix を入れて実検してみます。
0268デフォルトの名無しさん
2012/07/16(月) 00:55:59.93http://ideone.com/e6PGR
sumP と *^ を使ってみた。
kernelのsizeを約100、baseのsizeを約10000にして
ベンチマークフレームワーク ceriterion を使って測定してみたら、
15万倍くらいはやくなってる。39.45803 msから256.1315 nsヘ。
・・・マジで?
我ながら信じられないので、 ceriterion の使い方間違っているような気がする。
nsはナノ秒だよね? よね?
0269デフォルトの名無しさん
2012/07/16(月) 01:40:46.31SceneProcはステートマシンとしては普通の定義だと思う。
>やたら if や case of で場合分けする羽目になるということ。
そういう風に定義する計算モデルなのだから致し方ない。
ステートマシンを状態遷移表で書き下したとき、
・titleSceneやoptionScene等の関数が「状態」
・パターンやガードが「入力」
・その右辺式の値が「出力と遷移」 (ScreenDesc, SceneProc)
に対応していて、ミーリー型オートマトンを定義してる、と考えるといいと思う。
Monadiusの定義だとムーア型かな。
シーンを関数として作る、というのは方向性として間違ってないんじゃないかな。
各シーンの内部状態をさらにどうしてるかが問題だけど。
IORefを多用している事と、ステートマシンが分岐だらけであることとはあまり関連性がない気がする。
とりあえずステートマシンの参考になりそうな、有名所を適当に上げると、、
SceneProcの定義はYampaの定義が一番近いと思う。Netwireも確かこんなん。
これらの単純なモデルは、arrowsパッケージのAutomaton i o。(関数型プログラミングの楽しみ10章の単純オートマトン)
変種としては、
SceneProc r
= SP (Time -> GamePad -> (ScreenDesc, SceneProc r))
| Done r
と、Done rを付け加えるとモナドにできて、コルーチンみたいな中断/再開が可能になる。(Done rは受理状態に相当。)
Enumeratorとか、Conduit、Pipes、もこのタイプ。
これらをさらに抽象化したのがmonad-coroutineで、コイツは実はMonadFreeというものに解りやすい名前を付けただけ、
とか色々奥の深い世界があったりする。
MonadFreeの別の応用としてOperationalモナドというのもあったり…。(自動モナド化とか、インタプリタとか興味深かった)
0270デフォルトの名無しさん
2012/07/16(月) 02:15:42.25演算の中に畳み込みが入ってるなら、配列要素数に比例する以上の速度変化が出てもそれほど不思議じゃない
ただ、ghci環境でやってるなら速度計測はまったくアテにならない
exeファイルを作って計測すべき
0271デフォルトの名無しさん
2012/07/16(月) 04:49:51.07言葉を選んで口数少なく
あ、うん……
0272デフォルトの名無しさん
2012/07/16(月) 04:51:59.44アプリケイティヴって読んでた……:(;゙゚'ω゚'):
0273デフォルトの名無しさん
2012/07/16(月) 06:51:33.61ちょっとした間違いを見つけると厳しく指摘する神経質な理系女子…
ナンカイヤダ
0274デフォルトの名無しさん
2012/07/16(月) 07:43:11.050275デフォルトの名無しさん
2012/07/16(月) 08:02:09.32完全に同じイメージだった…
物静かだけど非常に厳しい
0276デフォルトの名無しさん
2012/07/16(月) 18:23:56.330277262
2012/07/16(月) 18:54:36.66この方向で洗練させていくには、結局俺は何を勉強してみるのがいいんだ?
ミーリー型オートマトンがどういったものか調べてみればいいのかな。
それとも、Yampa や Netwire や Automaton i o の中身を調べてみればいいのかな。
変種としては・・・以降の話は、基礎を学んだその後の話だよな、きっと。
0278237
2012/07/16(月) 19:48:07.97コンパイルして試してみたところ、calc1 の方の結果が、
ideone_e6PGR.exe: .\Data\Vector\Generic.hs:244 ((!)):
index out of bounds (-2147483648,100000)
ideone_e6PGR.exe: thread blocked indefinitely in an MVar operation
と表示されたのですが、何か問題あるでしょうか。
こちらの環境は、下記の通りです。
Intel Core2 Duo 2.4GHz メモリ 2GB
Windows7
ghc 7.4.1 (repa-3.2.1.1 criterion-0.6.0.1)
0279デフォルトの名無しさん
2012/07/17(火) 01:32:45.61ありがとう。
確かに、Windows 7環境だと、こっちでも同じエラーが出る。
というわけで、criterion周りを多少変えて、かつ新しい関数calc2を加えたコード
http://ideone.com/hdl0v
これだと、Windows 7だとcalc1はcalc0よりも遅い。
しかし、calc2はcalc0よりも数%だが速い。
別PCのUbuntuだと、calc2 > calc1 > calc0で速い。
しかも、calc2はcalc0の2倍くらい速い。
15万倍も速くなるなんていうのはおかしいから、前回の結果は測定方法に問題があったのだと思う
なお、ソフトのバージョンは両方とも
GHC 7.4.1
repa 3.1.0.1
criterion 0.6.0.1
0280デフォルトの名無しさん
2012/07/17(火) 01:34:14.90コンパイルするときに実行時のメモリ量を指定できるから、メモリを増加して実行しても同じメッセージが出るなら配列の添字指定でミスってる
メモリ増やしてエラーの配列のboundsの数字が変わるなら、メモリが足りなかったか、MVarでミスってる
0281デフォルトの名無しさん
2012/07/17(火) 01:47:31.39場合分けの嵐になるのはそういう状態マシンである以上仕方ないと思うけど、
IORefを多用しているというのが非常に気になる。
察するに、例えば、ゲームの自機や敵が動いているアクション画面(と呼ぼう)から
装備変更画面だとかコンフェグ画面だとかに遷移したあと、またアクション画面に戻ったとき、
自機や敵の位置など前回のアクション場面のパラメータが保存されてなければならないが、
それを装備変更画面だとかコンフェグ画面だとかの間中保持して受け渡し続けるのがうざい、
ということなんだろうか?
0282デフォルトの名無しさん
2012/07/17(火) 01:58:11.92IORefを避けるなら、ゲームのどの環境遷移も二分岐以下の合成で表現できるという制約をゲームの仕様にくっつけるべきではなかろうか
0283237
2012/07/17(火) 19:38:27.61試したところ、ちゃんとテストできました。
こちらでも同じ傾向が出ました。
calc1 は遅いですが、calc0 と calc2 がほぼ同じ速度です。
何回かテストすると 0 と 2 で順位が入れ替わることもあり、
差はたぶん誤差の範囲で済まされるレベルだと思います。
ただ、気になる点がひとつ。
defaultMain 関数でテストする関数をリストしていますが、
calc0 1 2 のテスト順をどう入れ替えても、最初にテストするものだけ、
かならず異常値によって発生した分散が 50% を越えます(80%いく時も)。
何なんでしょうかね。
あと、せっかくなんで RTS の -hc オプションを付けて
使用メモリの量や傾向も測ってみました。
こちらのテストでは、calc0 に対して calc1 と calc2 は
使用メモリ量が 10 倍高かったでかす。
と言っても、kernel=[1..100]、base=[1..10000] で 1 サイクルを計測して、
calc0 で 14kByte 強程度なので、たかが知れてますが。
そして、当然と言えば当然ですが、メモリ使用の傾向は
calc0 では綺麗な三角形に、calc1 や calc2 では台形になりました。
速度、メモリ双方のテストで少し意外(期待はずれ)な結果になりました。
このような1次元や2次元の畳み込み演算は応用も広く需要ありそうですが、
もっと綺麗に書ける専用関数をライブラリに入れてほしいものです。
今回は大変勉強にになりました。ありがとうございました。
0284デフォルトの名無しさん
2012/07/18(水) 08:26:34.33なんだ老婆か
0285デフォルトの名無しさん
2012/07/19(木) 13:35:25.39"you must not close the Handle until you have finished consuming its results <<via>> hGetContens.
Doing so would cause you to miss on some or all of the file's data."
とんだ落とし穴じゃないか。。。
0286デフォルトの名無しさん
2012/07/19(木) 13:42:02.590287デフォルトの名無しさん
2012/07/19(木) 14:09:02.87Lazy IO()の代わりにこれらを用いたRWHに相当する本が待たれるところ
0288デフォルトの名無しさん
2012/07/19(木) 15:26:55.330289デフォルトの名無しさん
2012/07/19(木) 19:32:40.39どういうコード書いたらこんな事態に遭遇するの?
0290デフォルトの名無しさん
2012/07/19(木) 21:19:09.81とか
0291デフォルトの名無しさん
2012/07/19(木) 22:50:12.66大量のファイルからデータを読み込んでデータベースに叩き込む処理を書いたときに、
OSのファイルディスクリプタの数の制限に引っかかって、ファイルを閉じる処理を入れたら、
これではまった。
まぁ、これも、ファイルを閉じる処理をデータを入れる処理の後に書けばすむ話だったわけで、
知っていれば容易に避けられる問題ではある。
0292デフォルトの名無しさん
2012/07/20(金) 01:45:59.810293デフォルトの名無しさん
2012/07/20(金) 11:20:14.00はあ
0294デフォルトの名無しさん
2012/07/20(金) 11:22:34.220295デフォルトの名無しさん
2012/07/20(金) 15:14:51.490296デフォルトの名無しさん
2012/07/20(金) 23:05:22.410297デフォルトの名無しさん
2012/07/21(土) 01:17:00.83型クラスをreifyしてもfamilyDなんかは見当たらないのに、
(その型クラス内での)型族をreifyすると普通に型クラスの型変数を共有してたりして、どう書いたら良いのか分からんのです
0298297
2012/07/21(土) 01:34:57.57お騒がせしてすいません
0299デフォルトの名無しさん
2012/07/22(日) 16:06:44.03ようわからんけど
無限リストの扱いみたいに、必要な分だけもらって後は知りませんよ的コードじゃなくて、
全部使う事を前提とした書き方の時は心配しなくていいってこと?
0300デフォルトの名無しさん
2012/07/22(日) 16:11:11.73遅延 IO に限らない話だが、
リソース(ハンドラ)を解放する前に、必要な分のデータを消費するなら、問題ない。
遅延 IO だと、必要な分のデータを消費する前にリソースが解放されてしまう可能性に、
ソースをぱっと見た限りではなかなか気づかない可能性が低くないことが問題。
0301デフォルトの名無しさん
2012/07/22(日) 16:24:37.280302デフォルトの名無しさん
2012/07/22(日) 16:51:24.81遅延 IO に関する問題で、>>300 に示したものについては、
hGetContents 関数や getContents 関数を使用した場合に多く見られる。
遅延 IO に関する問題は逆に、データが完全に消費する(読まれる、かな)まで
リソースが解放されない、という問題もある。
こちらは、readFile 関数などでよく見られる。
これらはあくまで私が自分でよく体験した問題です。
他にもあるかも知れません。
0303デフォルトの名無しさん
2012/07/22(日) 17:48:07.53引用元は↓のサンプルコード"ch07/toupper-lazy2.hs"のすぐ後にあるwarningですよ。
ttp://book.realworldhaskell.org/read/io.html
読者のコメントも付いてますね。
0304デフォルトの名無しさん
2012/07/23(月) 02:19:06.200305デフォルトの名無しさん
2012/07/23(月) 07:07:34.51俺はEmacsで十分だけど
0306デフォルトの名無しさん
2012/07/23(月) 08:14:53.53leksahも使ってみたけど結局Vimに落ち着いた
0307デフォルトの名無しさん
2012/07/23(月) 11:06:49.190308デフォルトの名無しさん
2012/07/23(月) 20:30:36.420309デフォルトの名無しさん
2012/07/23(月) 20:43:41.820310デフォルトの名無しさん
2012/07/23(月) 21:05:08.540311デフォルトの名無しさん
2012/07/23(月) 21:30:42.94fmapってなんなのか謎です。助けてくださいお願いします。
0312デフォルトの名無しさん
2012/07/23(月) 21:34:08.600313デフォルトの名無しさん
2012/07/23(月) 21:57:08.56動作よくわかりません。fmapってmapと何が違うの?
0314デフォルトの名無しさん
2012/07/23(月) 21:59:40.470315デフォルトの名無しさん
2012/07/23(月) 22:41:05.39入れ物っぽい動きをするデータ型の中身に関数を作用させるのがfmap
で、リストのfmapに特にmapと名前がついてるだけ
ていうかH本にそんな感じで書いてあったはずだが…
0316デフォルトの名無しさん
2012/07/23(月) 22:42:02.100317デフォルトの名無しさん
2012/07/23(月) 22:45:56.020318デフォルトの名無しさん
2012/07/23(月) 23:29:36.85実際の動作は型によってまちまち。
(a -> b) -> f a -> f b という型と若干の規則が共通しているだけ。
0319デフォルトの名無しさん
2012/07/23(月) 23:56:19.91data A a b = A a b
instance Functor (A a) where
f `fmap` (A a b) = A a (f b)
次のようなことはできる?
instance Functor (A * b) where
f `fmap` (A a b) = A (f a) b
* は一つ目の型引数に対して Functor を定義しているつもり。
もちろんこれはエラーなんだけど、意図は伝わったと思う。
GHC の拡張機能でできるようになる?
0320デフォルトの名無しさん
2012/07/24(火) 00:24:48.07instance Functor (B b) where ...
でできないかな
0321デフォルトの名無しさん
2012/07/24(火) 07:58:25.02fmap (*3) (+100) 1
なぞこれは、引数2でいいの?
fmap (replicate 3) [1,2,3]
0322デフォルトの名無しさん
2012/07/24(火) 08:09:46.54fmap :: (Functor f) -> (a -> b) -> f a -> f b
だから、基本的にはfmapは引数を二つ取る関数
fmap (replicate 3) [1,2,3::Int]
なら、f=[], a=Int, b=[Int]だから返り値の型はf b=[[Int]]
fmap (*3) (+(100::Int))
だと、f=(->)Int, a=Int, b=Intだから返り値の型はf b=Int->Int
ここからIntを得るにはもう一つ引数を与える必要がある
0323322
2012/07/24(火) 08:10:41.80これは
fmap :: (Functor f) => (a -> b) -> f a -> f b
の間違い
0324デフォルトの名無しさん
2012/07/24(火) 20:14:32.46Readerモナドが欲しい時はnewtype R a b = R (a -> b)のようにコンストラクタを明記した形でだけ使わせるべき
0325デフォルトの名無しさん
2012/07/24(火) 21:19:11.76(r ->) がインスタンスになってたって困ることないだろう。
気にいらないなら明示的に Reader, runReader 使えばいいじゃん。
0326デフォルトの名無しさん
2012/07/24(火) 21:38:02.81> join (+) === (2*) みたいなことができて便利。
すげー。
0327デフォルトの名無しさん
2012/07/24(火) 22:27:52.060328デフォルトの名無しさん
2012/07/24(火) 23:05:03.730329デフォルトの名無しさん
2012/07/25(水) 00:32:26.57よくわからない。何がすごいの?
0330デフォルトの名無しさん
2012/07/25(水) 01:02:38.56例えられれば例えられる程分からん。
0331デフォルトの名無しさん
2012/07/25(水) 01:05:26.320332デフォルトの名無しさん
2012/07/25(水) 01:08:47.29定数の2を使わずに済む
圧倒的難読化効率
わざわざMonad ((->) a)のインスタンスをインポートしなければならない
ぐらいしか思いつかない
0333デフォルトの名無しさん
2012/07/25(水) 04:23:23.00この例だけがすごいわけじゃなくて、
f x x みたいに同じ引数を二回使うとき、
join f x と書けるということ。
ようは runReader なしで使える Reader モナドなので、
共通の引数を使い回せる。
0334デフォルトの名無しさん
2012/07/25(水) 06:46:55.56を、ポイントフリーで
join (***) f
と書くのはたまに見る。俺は使わないけど
0335デフォルトの名無しさん
2012/07/25(水) 07:30:14.88H本に載ってないような?
0336デフォルトの名無しさん
2012/07/25(水) 07:38:38.47H本にも載ってるはず…
0337デフォルトの名無しさん
2012/07/25(水) 14:03:27.240338319
2012/07/25(水) 19:26:48.34こうしたらエラーが出た。
data A a b = A a b
type B b a = A a b
instance Functor (B b) where
f `fmap` (A a b) = A (f a) b
エラーメッセージ
Type synonym `B' should have 2 arguments, but has been given 1
In the instance declaration for `Functor (B b)'
こっちは GHC 7.4.1 使ってる。
0339デフォルトの名無しさん
2012/07/26(木) 12:12:16.640340319
2012/07/26(木) 12:38:04.82いや、俺もそう思うんだが、>>320 がこれでできるんちゃうかと・・・
結局、>>319 の事はできるのかできないのか、どうなんだろ?
0341デフォルトの名無しさん
2012/07/26(木) 15:05:07.43@PostgreSQLをインストールした場所のbinへパスを通します
これはSetupがpg_config.exeを実行できるようにする為でございます
Acabalファイルのextra-libraries: 欄で、pq → libpq とします
BHaskellをインストールした場所のmingw\lib にliblibpq.aを用意しておきます
これにはPostgreSQLをインストールした場所のlibからlibpq.dllをコピーして
上記へリネームします
インストール後は消して良いです
CPostgreSQLをインストールした場所のlibへパスを通します
因みにlibにはlibpq.dllが、(@で通した)binにはlibpq.dllがさらに参照する2つの.dllがあります
以上で後は普通にセットアップして動く筈でございます
因みに私個人の環境は
Windows2000 SP4、Haskell Platform2011.4.0.0、HDBC-postgresql-2.3.2.1、PostgreSQL9.0.3でございます
0342デフォルトの名無しさん
2012/07/26(木) 21:06:22.62何故Just 3は、Just 3なの?
0343デフォルトの名無しさん
2012/07/26(木) 21:15:08.580344デフォルトの名無しさん
2012/07/26(木) 21:16:17.080345デフォルトの名無しさん
2012/07/26(木) 21:42:08.680346デフォルトの名無しさん
2012/07/26(木) 22:46:14.73そうすると関数になるから色々な関数の引数に利用できるのかな?
0347デフォルトの名無しさん
2012/07/26(木) 22:49:06.000348デフォルトの名無しさん
2012/07/26(木) 22:53:10.850349デフォルトの名無しさん
2012/07/26(木) 22:54:55.34すると3になるんだよ。すごいね
0350デフォルトの名無しさん
2012/07/26(木) 22:59:40.020351デフォルトの名無しさん
2012/07/26(木) 23:53:20.390352デフォルトの名無しさん
2012/07/26(木) 23:55:31.660353デフォルトの名無しさん
2012/07/27(金) 00:14:48.20じゃあHaskellの型って群なの?
0354デフォルトの名無しさん
2012/07/27(金) 01:09:05.200355デフォルトの名無しさん
2012/07/27(金) 01:19:40.57でしょうか?
0356デフォルトの名無しさん
2012/07/27(金) 01:26:37.080357デフォルトの名無しさん
2012/07/27(金) 01:28:03.190358デフォルトの名無しさん
2012/07/27(金) 01:30:49.100359デフォルトの名無しさん
2012/07/27(金) 01:36:06.29ttp://www.amazon.co.jp/dp/4274068854
この本買ってきて頭から読むと良いよ、Maybeまでなら土日使えば辿りつけるはず
ここで散発的な質問するより絶対そっちの方が早いから
0360デフォルトの名無しさん
2012/07/27(金) 08:08:49.030361デフォルトの名無しさん
2012/07/27(金) 09:05:16.02ハアハア
0362デフォルトの名無しさん
2012/07/27(金) 12:07:44.57■ このスレッドは過去ログ倉庫に格納されています