関数型プログラミング言語 Haskell について語るスレです。
haskell.org (公式サイト)
http://www.haskell.org/
前スレ
関数型プログラミング言語Haskell Part28
http://echo.2ch.net/test/read.cgi/tech/1428597032/
探検
関数型プログラミング言語Haskell Part30 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
2017/01/15(日) 23:43:54.28ID:Vh4eztBk
762デフォルトの名無しさん
2017/07/29(土) 21:13:59.96ID:GuKX0EtE メモリー管理が陽に出てこないGC言語でGCについて語るAPIが存在するのも美しくないな
待機型処理の内部に組み入れられないんだろうか
待機型処理の内部に組み入れられないんだろうか
763_
2017/07/29(土) 21:43:41.58ID:z3bKXBTm ghc 8.2.1リリース
age
age
764デフォルトの名無しさん
2017/07/29(土) 22:00:35.21ID:ezVHy3/u 実行頻度不明なのに強制GCしたらGCのオーバーヘッドに食い尽くされる可能性あるやろ
人力か機械学習でGCポイント探すしかないわ
線形型はよ
人力か機械学習でGCポイント探すしかないわ
線形型はよ
765デフォルトの名無しさん
2017/07/29(土) 22:05:39.73ID:EGnuLLJd Numeric Prelude標準モードできねえかな
766デフォルトの名無しさん
2017/07/30(日) 18:38:08.27ID:Qtbkg44k いつになったらGHCのコードに型を記述するんだよ
あんなコードじゃ常に参加してる奴しか解読出来ないだろ
あんなコードじゃ常に参加してる奴しか解読出来ないだろ
767デフォルトの名無しさん
2017/08/02(水) 14:19:58.09ID:nRMWmSFr デバッグで行単位で進める、
変数の値を都度観察できる、みたいなエディタというかIDEってありますかね?
変数の値を都度観察できる、みたいなエディタというかIDEってありますかね?
768デフォルトの名無しさん
2017/08/02(水) 15:25:19.26ID:D+JhlBxR デバッグで苦しんだことがないから分からないが
観察するべき実行時エラーが出るものなのか
必死に型を記述した結果がこれか
観察するべき実行時エラーが出るものなのか
必死に型を記述した結果がこれか
769デフォルトの名無しさん
2017/08/02(水) 15:33:23.39ID:W2G2gcC4 >>767
ghciのデバッガじゃいかんの?
ghciのデバッガじゃいかんの?
770デフォルトの名無しさん
2017/08/02(水) 23:16:44.52ID:Fofa317S771デフォルトの名無しさん
2017/08/03(木) 00:12:26.54ID:Ip+Lj8Tk 純粋関数のprintデバッグができるDebug.Traceとかどうですか
772デフォルトの名無しさん
2017/08/03(木) 07:59:11.85ID:d2xIcHkQ プログラミング初心者だけど将来Haskell用のデバッガを作るのが夢です
773デフォルトの名無しさん
2017/08/03(木) 08:47:54.62ID:jTGWEJQg ジーニアス英和辞典 第五版にぴったりの例文があった
Passion without action is??merely??a dream.
Passion without action is??merely??a dream.
774デフォルトの名無しさん
2017/08/03(木) 08:53:44.89ID:z5sKoHNx デバッガよりVisual Studio並みの最強IDEがほしいわ
775デフォルトの名無しさん
2017/08/03(木) 22:43:53.87ID:PWpQLJ0B Bounded クラスと Enum クラスのインスタンスである型 T について、
n 個の要素を持つリスト型 [T] の値を全て要素として持つリストを生成する関数を enumerate とします。
たとえば型 T の値が A と B の2つだとし、n=3 だとすると、
(enumerate 3 :: [T]) = [[A, A, A], [A, A, B], [A, B, A], [A, B, B], [B, A, A], [B, A, B], [B, B, A], [B, B, B]]
となります。
ただし、生成されるリストの要素の順番は問いません。
私は下記のように定義しました。
enumerate :: (Bounded a, Enum a) => Int -> [[a]]
enumerate 1 = map (:[]) [minBound .. maxBound]
enumerate n = concatMap (\x -> map (x:) (enumerate (n-1))) [minBound .. maxBound]
n-1個の既に作られたリストの各要素 (リスト) に新たに型 T のそれぞれの値を接頭する作り方です。
シンプルで分かりやすいのですが、問題が1つあります。
この関数が生成したリストの全要素を順に別の計算に消費するようなプログラムを作っているのですが、
上記の定義ですと、リストの全要素が消費し尽くされるまでほぼ全要素分のメモリが必要になります。
x : x : x : ... と積み上がった cons がメモリに残るような作りのためです。
消費は順に一つずつ行うので、理想的にはメモリも要素一つ分で足ります。
現実はそうもいかないと思いますが、全要素分のメモリを保持し続ける必要はないはずです。
メモリ消費量をもっと抑える良い方法はないでしょうか。
n 個の要素を持つリスト型 [T] の値を全て要素として持つリストを生成する関数を enumerate とします。
たとえば型 T の値が A と B の2つだとし、n=3 だとすると、
(enumerate 3 :: [T]) = [[A, A, A], [A, A, B], [A, B, A], [A, B, B], [B, A, A], [B, A, B], [B, B, A], [B, B, B]]
となります。
ただし、生成されるリストの要素の順番は問いません。
私は下記のように定義しました。
enumerate :: (Bounded a, Enum a) => Int -> [[a]]
enumerate 1 = map (:[]) [minBound .. maxBound]
enumerate n = concatMap (\x -> map (x:) (enumerate (n-1))) [minBound .. maxBound]
n-1個の既に作られたリストの各要素 (リスト) に新たに型 T のそれぞれの値を接頭する作り方です。
シンプルで分かりやすいのですが、問題が1つあります。
この関数が生成したリストの全要素を順に別の計算に消費するようなプログラムを作っているのですが、
上記の定義ですと、リストの全要素が消費し尽くされるまでほぼ全要素分のメモリが必要になります。
x : x : x : ... と積み上がった cons がメモリに残るような作りのためです。
消費は順に一つずつ行うので、理想的にはメモリも要素一つ分で足ります。
現実はそうもいかないと思いますが、全要素分のメモリを保持し続ける必要はないはずです。
メモリ消費量をもっと抑える良い方法はないでしょうか。
776デフォルトの名無しさん
2017/08/04(金) 03:26:35.06ID:F7/4gW8S >>775
ちゃんとプロファイル取ってないから確証はないけど
enumerateの定義が悪くてメモリ食いすぎてるような気がする
Control.Monad のreplicateMをリストモナドに対して使うと
同様に重複順列を作れるからそれならどうだろうか
replicateM 3 [0, 1] -- > [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
あとリストを順に消費していくような計算ならfoldl'が使えるはず
あるいは、「EnumなT型の有限個の直積」をうまく新たにEnumのインスタンスにして、
succ: Enum a => a -> a
で例えば succ [A, A, A] = [A, A, B]
みたいに計算できるようにしておいて、
STRefを利用してsuccで更新しながら消費していく、とか
ちゃんとプロファイル取ってないから確証はないけど
enumerateの定義が悪くてメモリ食いすぎてるような気がする
Control.Monad のreplicateMをリストモナドに対して使うと
同様に重複順列を作れるからそれならどうだろうか
replicateM 3 [0, 1] -- > [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
あとリストを順に消費していくような計算ならfoldl'が使えるはず
あるいは、「EnumなT型の有限個の直積」をうまく新たにEnumのインスタンスにして、
succ: Enum a => a -> a
で例えば succ [A, A, A] = [A, A, B]
みたいに計算できるようにしておいて、
STRefを利用してsuccで更新しながら消費していく、とか
777デフォルトの名無しさん
2017/08/04(金) 06:02:27.89ID:dl0ZTbjy https://wandbox.org/permlink/jdlx4FhKT80IWQKN
data T = A | B deriving Show
hoge 0 = A
hoge 1 = B
fuga _ 0 _ = []
fuga k x n = let (d,m) = divMod n k in hoge m : fuga k (x-1) d
piyo x = map (fuga 2 x) [0..2^x-1]
main = print $ piyo 3
data T = A | B deriving Show
hoge 0 = A
hoge 1 = B
fuga _ 0 _ = []
fuga k x n = let (d,m) = divMod n k in hoge m : fuga k (x-1) d
piyo x = map (fuga 2 x) [0..2^x-1]
main = print $ piyo 3
778デフォルトの名無しさん
2017/08/04(金) 07:58:50.98ID:QkUZB/64 >>775
import Data.List
enumerate 1 = map (:[]) [1..]
enumerate n = concatMap (\x -> map (x:) (enumerate (n-1))) [1..]
main = print $ foldl' (+) 0 $ map (foldl' (+) 0) $ enumerate 10000
これ(最適化無し)でメモリリークしないあたり
普通に深さ優先で要らなくなった枝はGCされてると思うけど
import Data.List
enumerate 1 = map (:[]) [1..]
enumerate n = concatMap (\x -> map (x:) (enumerate (n-1))) [1..]
main = print $ foldl' (+) 0 $ map (foldl' (+) 0) $ enumerate 10000
これ(最適化無し)でメモリリークしないあたり
普通に深さ優先で要らなくなった枝はGCされてると思うけど
779デフォルトの名無しさん
2017/08/04(金) 08:14:23.88ID:QkUZB/64 あー>>778だと最後の一個が変わり続けるだけだから例としてはダメか
一応enumerateの引数やEnumリストの長さを変えてみても大丈夫だったけど
一応enumerateの引数やEnumリストの長さを変えてみても大丈夫だったけど
780デフォルトの名無しさん
2017/08/04(金) 22:00:01.39ID:dl0ZTbjy そんなことより8月4日21時から72時間のICFPのプログラミングコンテストがあるよ!
HaskellerならICFPくらい知ってるよね!
http://events.inf.ed.ac.uk/icfpcontest2017/
https://twitter.com/ICFPContest2017
HaskellerならICFPくらい知ってるよね!
http://events.inf.ed.ac.uk/icfpcontest2017/
https://twitter.com/ICFPContest2017
781デフォルトの名無しさん
2017/08/04(金) 22:13:55.04ID:hukhoKmj みなさん、ありがとうございます。
>>776
前半の replicateM を使う方法は、プロファイリングしてみましたが、私のものとほとんど同じ結果でした。
メモリ消費の傾向もピークも同じ形です。
enumerate 14 で試したところ、最初にピークの 100MB ほどまでぐんぐんメモリを消費し、
その後 90MB 近くまで落ちてから一定です。
後半の方法はこれから試してみます。
>>777
挙げていただいたコードを Bounded と Enum を使って一般化して試してみました。
同様に enumerate 14 で実行してみると、メモリ消費傾向は全体的にほぼまっすぐな長方形に近い台形で、
ピークも 40kB と桁違いに少ないです。
>>778
メモリリークが起きていないことはどのようにして確認されました?
私は実行する時に RTS オプションの hc を付けてプロファイルを取って確認しました。
確かに深さ優先で一度ずつ探索する処理なのに、メモリが 100MB も消費されていて、
これは明らかにメモリリークしていると思ったのですが、どうでしょう?
これから、私や >>776 の前半のやり方と >>777 のやり方の違いについて研究してみます。
>>776
前半の replicateM を使う方法は、プロファイリングしてみましたが、私のものとほとんど同じ結果でした。
メモリ消費の傾向もピークも同じ形です。
enumerate 14 で試したところ、最初にピークの 100MB ほどまでぐんぐんメモリを消費し、
その後 90MB 近くまで落ちてから一定です。
後半の方法はこれから試してみます。
>>777
挙げていただいたコードを Bounded と Enum を使って一般化して試してみました。
同様に enumerate 14 で実行してみると、メモリ消費傾向は全体的にほぼまっすぐな長方形に近い台形で、
ピークも 40kB と桁違いに少ないです。
>>778
メモリリークが起きていないことはどのようにして確認されました?
私は実行する時に RTS オプションの hc を付けてプロファイルを取って確認しました。
確かに深さ優先で一度ずつ探索する処理なのに、メモリが 100MB も消費されていて、
これは明らかにメモリリークしていると思ったのですが、どうでしょう?
これから、私や >>776 の前半のやり方と >>777 のやり方の違いについて研究してみます。
782デフォルトの名無しさん
2017/08/05(土) 02:29:47.95ID:B0WoWMTx783デフォルトの名無しさん
2017/08/05(土) 03:50:29.84ID:pRMdXxul >>781
40KBはありえないので一般化に失敗してると思われる
40KBはありえないので一般化に失敗してると思われる
784デフォルトの名無しさん
2017/08/05(土) 04:37:17.71ID:2UARNcsu >>782
メモ化は空間計算量と引き換えに高速化する話だからむしろ逆のような
フィボナッチで言うならInteger 3個分のメモリがあればn番目が計算できるでしょって話だから
タプリングの方が解決策としては近いと思う
結局リストで定義しちゃうと(そして評価しちゃうと)
そのイミュータブル性のために各要素はまた参照されるかもしれないから
GHCは捨てられないんだと思ってる
メモ化は空間計算量と引き換えに高速化する話だからむしろ逆のような
フィボナッチで言うならInteger 3個分のメモリがあればn番目が計算できるでしょって話だから
タプリングの方が解決策としては近いと思う
結局リストで定義しちゃうと(そして評価しちゃうと)
そのイミュータブル性のために各要素はまた参照されるかもしれないから
GHCは捨てられないんだと思ってる
785デフォルトの名無しさん
2017/08/05(土) 05:35:09.29ID:pRMdXxul /usr/bin/time -f "sec: %e\tmem: %M"
で
n=13
>>775の sec: 0.36 mem: 89032
https://paiza.io/projects/EvT2VA9nWlsu95GfM7llhA
>>776の replicateM は sec: 0.38 mem: 89016 と確かにメモリそう変わらない
https://paiza.io/projects/-jBpd8K5u3IcfeqromaImg
>>777の変な奴は sec: 0.86 mem: 3856 と確かにメモリ少ないけど時間かかりすぎ
https://paiza.io/projects/k_jsvUVfq54JyTaA691CaQ
>>782の iterate は sec: 0.36 mem: 77668 と少しメモリ小さい
https://paiza.io/projects/rb9bWzNuI410te_SxtMqMw
で
n=13
>>775の sec: 0.36 mem: 89032
https://paiza.io/projects/EvT2VA9nWlsu95GfM7llhA
>>776の replicateM は sec: 0.38 mem: 89016 と確かにメモリそう変わらない
https://paiza.io/projects/-jBpd8K5u3IcfeqromaImg
>>777の変な奴は sec: 0.86 mem: 3856 と確かにメモリ少ないけど時間かかりすぎ
https://paiza.io/projects/k_jsvUVfq54JyTaA691CaQ
>>782の iterate は sec: 0.36 mem: 77668 と少しメモリ小さい
https://paiza.io/projects/rb9bWzNuI410te_SxtMqMw
786デフォルトの名無しさん
2017/08/05(土) 11:12:37.24ID:xs6w3tHN iterateは良いよね
iterateはメモリを無限に使うとか予想したやつを退場させてから冷静な議論ができる
iterateはメモリを無限に使うとか予想したやつを退場させてから冷静な議論ができる
787デフォルトの名無しさん
2017/08/05(土) 11:39:14.63ID:ZbIs+TkB 好戦的
788デフォルトの名無しさん
2017/08/05(土) 13:37:30.60ID:xs6w3tHN 人間を退場させそうな勢いのAIに同じことが言えるのかね
好戦的AIの開発を禁止できるのか
好戦的AIの開発を禁止できるのか
789デフォルトの名無しさん
2017/08/05(土) 20:09:57.57ID:O1n7JOVS Windowsでjupyterできませんか?
790デフォルトの名無しさん
2017/08/06(日) 00:35:09.20ID:Q0UOjaQj791デフォルトの名無しさん
2017/08/06(日) 14:15:08.49ID:PBiILbDw792デフォルトの名無しさん
2017/08/07(月) 02:20:55.75ID:LndoSP5N 未評価のサンクじゃなくて最終的にn-1以下の評価済み結果を全て保持することになるからメモリを食うのでは?
793デフォルトの名無しさん
2017/08/07(月) 09:52:01.96ID:/JDQv1Xc 自由な長さのビットは標準ライブラリに無いのですか?
794デフォルトの名無しさん
2017/08/07(月) 11:32:36.95ID:EbDwvOe5795デフォルトの名無しさん
2017/08/07(月) 20:00:07.36ID:Nk2fFjGd >>789
dockerでihaskellだったら使ってる
dockerでihaskellだったら使ってる
796デフォルトの名無しさん
2017/08/07(月) 21:16:35.72ID:AGrOxn5I >>792
そうでしょうか?
私の方法 (>>775) で data T = A|B|C の時に print $ enumerate 3 としてみると
[[A,A,A], [A,A,B], [A,A,C], [A,B,A], [A,B,B], ...] の順で評価されます。
外側リストの第1要素 [A,A,A] を評価し終えて次に第2要素 [A,A,B] を評価しようとする時、
[A,A,A] の第3要素の A はもう要らないので捨てて構わないはずです。
[A,A,B] の評価にまだ必要なのは第1要素と第2要素それぞれの A のみのはず。
さらに [B,A,A] まで評価が進めば、[A,A,A] から [A,C,C] まで評価した分はもう必要ありません。
そう考えると、enumerate n に常に必要なのは理論的には T 型の値 n 個分のみ。
評価済みの値の保持に必要なメモリ量は >>777 や >>790 の方法と同じです。
なので、評価済み結果の保持によってメモリが大きく消費されるのであれば、
>>777 や >>790 でも同様に大きなメモリを消費しているはずだと私は思うのですが、
どうでしょうか?
そうでしょうか?
私の方法 (>>775) で data T = A|B|C の時に print $ enumerate 3 としてみると
[[A,A,A], [A,A,B], [A,A,C], [A,B,A], [A,B,B], ...] の順で評価されます。
外側リストの第1要素 [A,A,A] を評価し終えて次に第2要素 [A,A,B] を評価しようとする時、
[A,A,A] の第3要素の A はもう要らないので捨てて構わないはずです。
[A,A,B] の評価にまだ必要なのは第1要素と第2要素それぞれの A のみのはず。
さらに [B,A,A] まで評価が進めば、[A,A,A] から [A,C,C] まで評価した分はもう必要ありません。
そう考えると、enumerate n に常に必要なのは理論的には T 型の値 n 個分のみ。
評価済みの値の保持に必要なメモリ量は >>777 や >>790 の方法と同じです。
なので、評価済み結果の保持によってメモリが大きく消費されるのであれば、
>>777 や >>790 でも同様に大きなメモリを消費しているはずだと私は思うのですが、
どうでしょうか?
797デフォルトの名無しさん
2017/08/07(月) 21:17:23.45ID:AGrOxn5I >>792
私が原因はサンクにあるのではと思ったのは次のことからです。
私の方法 (>>775) で enumerate 3 :: [[T]] の第1要素を評価しようとする時、
まず concatMap の引数である [minBound .. maxBound] の第1要素だけが評価され、
残りは未評価のまま残ります (正確には enumFromTo の結果の弱頭部正規化ですね)。
次に map (x:) enumerate (n-1) があるので enumerate 2 の第1要素を評価する必要があります。
enumerate 2 でも同様のことが起こります。
これ、全部評価されつくされるまで、深さ分だけずっと残りますよね。
enumerate 自身が深さ方向にたどるごとに毎回呼ばれ、評価し切る前にまた呼ばれるので、
未評価で残るのは [minBound .. maxBound] の部分だけではないと思います。
このようなことが積み重なって、大量のメモリ消費に繋がっていると私は考えました。
リストを消費して何かを計算する関数に使うリストそのものを再帰的に作ると、
たぶん似たような事(無駄なメモリ消費)が起こるのではないかと思います。
私が原因はサンクにあるのではと思ったのは次のことからです。
私の方法 (>>775) で enumerate 3 :: [[T]] の第1要素を評価しようとする時、
まず concatMap の引数である [minBound .. maxBound] の第1要素だけが評価され、
残りは未評価のまま残ります (正確には enumFromTo の結果の弱頭部正規化ですね)。
次に map (x:) enumerate (n-1) があるので enumerate 2 の第1要素を評価する必要があります。
enumerate 2 でも同様のことが起こります。
これ、全部評価されつくされるまで、深さ分だけずっと残りますよね。
enumerate 自身が深さ方向にたどるごとに毎回呼ばれ、評価し切る前にまた呼ばれるので、
未評価で残るのは [minBound .. maxBound] の部分だけではないと思います。
このようなことが積み重なって、大量のメモリ消費に繋がっていると私は考えました。
リストを消費して何かを計算する関数に使うリストそのものを再帰的に作ると、
たぶん似たような事(無駄なメモリ消費)が起こるのではないかと思います。
798デフォルトの名無しさん
2017/08/08(火) 00:32:40.42ID:ix2x2634 sumじゃなくlenghtで計算すると>>790のでもメモリ使うんだね
>>775のsec: 0.19 mem: 89068
https://paiza.io/projects/CqJoDIkGAnH7qGSCKEAiyQ
>>790のsec: 0.09 mem: 49084
https://paiza.io/projects/L4gRQ7RM5z3XFGf_Wu1YvQ
>>775のsec: 0.19 mem: 89068
https://paiza.io/projects/CqJoDIkGAnH7qGSCKEAiyQ
>>790のsec: 0.09 mem: 49084
https://paiza.io/projects/L4gRQ7RM5z3XFGf_Wu1YvQ
799デフォルトの名無しさん
2017/08/08(火) 03:20:35.89ID:fUnlTWTU 副作用の無い関数は同じ引数で毎回同じ戻り値になることが保証されてます
n=2のとき
enumerate 2 = concatMap (\x -> map (x:) (enumerate 1)) [A,B,C]
となります
[A,A]..[A,C]まで評価が終わったとき enumerate 1 = [[A],[B],[C]] が評価済みとなり再利用が可能となり
enumerate 2 = [A,A] : [A,B] : [A,C] : concatMap (\x -> map (x:) [[A],[B],[C]]) [B,C]
となり n-1 すなわち n=1 のときの結果が保持されることが分かります
同様にn=3のとき同じことが生じ
enumerate 3 = [A,A,A] : ... : [A,C,C] : concatMap (\x -> map (x:) [[A,A], ... ,[C,C]]) [B,C]
のようになり n-1 すなわち n=2 のときの結果が保持されることが分かります
また n=3 のとき n=1 の結果の [[A],[B],[C]] の各要素は n=2 の結果から参照されてます
すなわちGC可能な対象は 中身の[A] [B] [C]ではなく[,,,]の外側の部分だけです
(もちろんまだ enumerate 1 をどこか呼び出される可能性があるならGCはされませんが…)
ここまで言えば>>792の意味がわかりますね?
はい
n=2のとき
enumerate 2 = concatMap (\x -> map (x:) (enumerate 1)) [A,B,C]
となります
[A,A]..[A,C]まで評価が終わったとき enumerate 1 = [[A],[B],[C]] が評価済みとなり再利用が可能となり
enumerate 2 = [A,A] : [A,B] : [A,C] : concatMap (\x -> map (x:) [[A],[B],[C]]) [B,C]
となり n-1 すなわち n=1 のときの結果が保持されることが分かります
同様にn=3のとき同じことが生じ
enumerate 3 = [A,A,A] : ... : [A,C,C] : concatMap (\x -> map (x:) [[A,A], ... ,[C,C]]) [B,C]
のようになり n-1 すなわち n=2 のときの結果が保持されることが分かります
また n=3 のとき n=1 の結果の [[A],[B],[C]] の各要素は n=2 の結果から参照されてます
すなわちGC可能な対象は 中身の[A] [B] [C]ではなく[,,,]の外側の部分だけです
(もちろんまだ enumerate 1 をどこか呼び出される可能性があるならGCはされませんが…)
ここまで言えば>>792の意味がわかりますね?
はい
800デフォルトの名無しさん
2017/08/08(火) 03:28:04.28ID:fUnlTWTU なおサンクを気にされてたようですが
サンクを気おつけるべきは>>790のようなコードだと私は考えますが
lastを取れば分かります
https://paiza.io/projects/lmYXW-sssdTlAIGrju4u9g
サンクを気おつけるべきは>>790のようなコードだと私は考えますが
lastを取れば分かります
https://paiza.io/projects/lmYXW-sssdTlAIGrju4u9g
801デフォルトの名無しさん
2017/08/08(火) 03:45:42.60ID:aoRcppZr >>796
>外側リストの第1要素 [A,A,A] を評価し終えて次に第2要素 [A,A,B] を評価しようとする時、
>[A,A,A] の第3要素の A はもう要らない
後ろ二つ [A,A]は、[A,A,A],[B,A,A],[C,A,A]で共有されるから
そこで捨てるわけにはいかないんじゃないかな
>外側リストの第1要素 [A,A,A] を評価し終えて次に第2要素 [A,A,B] を評価しようとする時、
>[A,A,A] の第3要素の A はもう要らない
後ろ二つ [A,A]は、[A,A,A],[B,A,A],[C,A,A]で共有されるから
そこで捨てるわけにはいかないんじゃないかな
802デフォルトの名無しさん
2017/08/08(火) 04:31:27.11ID:shTh0A51 詳しい情報サンクス
803デフォルトの名無しさん
2017/08/08(火) 21:31:40.60ID:OEct+pCd >>799
すいません、まだ良く理解できていません。
2点確認させてください。
まず、1行目でおっしゃっているのは参照透過性のことですよね。
次に、3行目以降でおっしゃっていることですが、それは本当ですか?
それだと勝手にメモ化が行われているように私には見えるのですが。
例えば f x = x*2 という関数が定義されているとします。
その時に、別の関数 g の定義の中で、
let a = f 1; b = f 1 in ...
とやっても、1度目の g の呼び出しで 1*2 の計算結果は再利用されませんよね。
a の束縛時と b の束縛時で、計 2 回同じ計算がされると思います。
1度目の g の呼び出しで a や b が 2 と評価された後、再び g が呼ばれた時は、
a や b はもう関数 f ではなく値 2 を指していますから、
これを以て「保存される」「再利用される」と言うのは理解できます。
以上のことから、enumerate 1 = [[A], [B], [C]] のリストも、
このままでは再利用されないと思うのですが。
再利用するには、計算結果を変数に束縛する必要がありませんか。
変なことを言っていたらすいません。
すいません、まだ良く理解できていません。
2点確認させてください。
まず、1行目でおっしゃっているのは参照透過性のことですよね。
次に、3行目以降でおっしゃっていることですが、それは本当ですか?
それだと勝手にメモ化が行われているように私には見えるのですが。
例えば f x = x*2 という関数が定義されているとします。
その時に、別の関数 g の定義の中で、
let a = f 1; b = f 1 in ...
とやっても、1度目の g の呼び出しで 1*2 の計算結果は再利用されませんよね。
a の束縛時と b の束縛時で、計 2 回同じ計算がされると思います。
1度目の g の呼び出しで a や b が 2 と評価された後、再び g が呼ばれた時は、
a や b はもう関数 f ではなく値 2 を指していますから、
これを以て「保存される」「再利用される」と言うのは理解できます。
以上のことから、enumerate 1 = [[A], [B], [C]] のリストも、
このままでは再利用されないと思うのですが。
再利用するには、計算結果を変数に束縛する必要がありませんか。
変なことを言っていたらすいません。
804デフォルトの名無しさん
2017/08/08(火) 21:58:17.33ID:aoRcppZr805デフォルトの名無しさん
2017/08/08(火) 22:23:03.19ID:OEct+pCd >>804
仮引数が束縛しているのはそのスコープ内だけだと思っていましたが、
違うのでしょうか。
let a = map id (enumerate 1); b = map id (enumerate 1)
これは2度同じ計算 (enumerate 1 の評価) がされませんか?
仮引数が束縛しているのはそのスコープ内だけだと思っていましたが、
違うのでしょうか。
let a = map id (enumerate 1); b = map id (enumerate 1)
これは2度同じ計算 (enumerate 1 の評価) がされませんか?
806デフォルトの名無しさん
2017/08/08(火) 22:33:15.60ID:aoRcppZr 実際に起こっているのはこういうことなんだろうな
let a = map id (enumerate 1); b = a; c=a
let a = map id (enumerate 1); b = a; c=a
807デフォルトの名無しさん
2017/08/09(水) 00:17:08.56ID:VTzajaTq >>799-800
嘘乙
嘘乙
808デフォルトの名無しさん
2017/08/09(水) 02:22:31.31ID:mQsXelmt Glasgow Haskell Compiler上の遅延オブジェクト再利用手法の設計と実装
https://www.jstage.jst.go.jp/article/jssst/32/1/32_1_253/_pdf
https://www.jstage.jst.go.jp/article/jssst/32/1/32_1_253/_pdf
809デフォルトの名無しさん
2017/08/09(水) 05:51:36.85ID:L1lV7cdZ ・愚直にパラメーターマシマシの関数
・そのごちゃごちゃしたパラメーターをデータ構造にまとめてコードの視認性と一目理解可能性を向上したコード
後者が前者より2倍近く時間かかって悲しい
データ構造の更新に思いの外時間がかかってるのだろうか
データ構造の一部だけ更新って、変える部分だけ新しく作って、後のパラメーターは元のデータのそれへポインタコピーするだけだと思うんですけど
それでもオーバーヘッド嵩むもんなんすかね
ごちゃごちゃ版の、一つパラメーター更新して再帰で関数呼び出すだけなのと、
データ構造にまとめた版の(データ構造の)一つパラメーター更新して再帰で関数呼び出すのとは
何が処理の手間的に違うんですかね
いいからパラメーター全部そのまま関数に並べ立てた方が速いんだよって言われてるようで悲しい
性能を犠牲にせずにメンテ力アップしたい
・そのごちゃごちゃしたパラメーターをデータ構造にまとめてコードの視認性と一目理解可能性を向上したコード
後者が前者より2倍近く時間かかって悲しい
データ構造の更新に思いの外時間がかかってるのだろうか
データ構造の一部だけ更新って、変える部分だけ新しく作って、後のパラメーターは元のデータのそれへポインタコピーするだけだと思うんですけど
それでもオーバーヘッド嵩むもんなんすかね
ごちゃごちゃ版の、一つパラメーター更新して再帰で関数呼び出すだけなのと、
データ構造にまとめた版の(データ構造の)一つパラメーター更新して再帰で関数呼び出すのとは
何が処理の手間的に違うんですかね
いいからパラメーター全部そのまま関数に並べ立てた方が速いんだよって言われてるようで悲しい
性能を犠牲にせずにメンテ力アップしたい
810デフォルトの名無しさん
2017/08/09(水) 05:57:53.35ID:L1lV7cdZ 多くの場合を受け取って、後でcaseなどで引数の場合分けをするより
トップレベルで最初に引数のパターンマッチで場合分けしてから始める書き方の方が速いんですかね
後者はなんか何度も関数名書かなきゃいけなくて汚い感じするんですが。同じlet式もボイラープレートのようにまた書かなきゃならないし
でも後者の方が高速動作する(経験則)みたいで悔しい
トップレベルで最初に引数のパターンマッチで場合分けしてから始める書き方の方が速いんですかね
後者はなんか何度も関数名書かなきゃいけなくて汚い感じするんですが。同じlet式もボイラープレートのようにまた書かなきゃならないし
でも後者の方が高速動作する(経験則)みたいで悔しい
811デフォルトの名無しさん
2017/08/09(水) 07:31:58.59ID:azQJOuJj vectorパッケージ使ってて、ベンチマークとるとVector.Fusion.UtilとVector.Fusion.Stream.Monadicにリソースが割かれてるんだけど、
stream fusionてコンパイル時に効いてて、ランタイム時には出てこないと思ってたのだが、違うんかね?
stream fusionてコンパイル時に効いてて、ランタイム時には出てこないと思ってたのだが、違うんかね?
812デフォルトの名無しさん
2017/08/10(木) 00:20:12.66ID:joXozDrb 本物のプログラマはHaskellを使う - 第31回
http://itpro.nikkeibp.co.jp/article/COLUMN/20090512/329783/
> これは,GHCの最適化機能の一つである「共通部分式の削除(CSE:Common Subexpression Elimination)」によって,共通する式「unsafeVal 10」がメモ化されたためです。これにより「unsafeVal 10」は1回しか評価・実行されなくなってしまいます。
http://itpro.nikkeibp.co.jp/article/COLUMN/20090512/329783/
> これは,GHCの最適化機能の一つである「共通部分式の削除(CSE:Common Subexpression Elimination)」によって,共通する式「unsafeVal 10」がメモ化されたためです。これにより「unsafeVal 10」は1回しか評価・実行されなくなってしまいます。
813デフォルトの名無しさん
2017/08/10(木) 00:21:53.72ID:joXozDrb > Haskellには第8回で説明した「メモ化」という機能があるため,同じ式が複数回,評価・実行されることはありません。
814デフォルトの名無しさん
2017/08/10(木) 01:41:50.38ID:wtM226NM >>809
パラメータごちゃごちゃってのが多引数関数なら、Haskellの関数はカリー化されてるので
変更するパラメータの箇所によっては関数定義が使いまわせて効率がよくなってる、かも
末尾再帰化で局所関数作ってやるみたいに、
外からは定義したデータ構造で受け取って、
関数内で再帰回すときはばらした局所関数を使うとかはどうか
パラメータごちゃごちゃってのが多引数関数なら、Haskellの関数はカリー化されてるので
変更するパラメータの箇所によっては関数定義が使いまわせて効率がよくなってる、かも
末尾再帰化で局所関数作ってやるみたいに、
外からは定義したデータ構造で受け取って、
関数内で再帰回すときはばらした局所関数を使うとかはどうか
815デフォルトの名無しさん
2017/08/10(木) 06:48:00.63ID:Gy6ZNt2K メモ化じゃなくてグラフ簡約では?
816デフォルトの名無しさん
2017/08/10(木) 07:14:52.40ID:7mVrofJh http://itpro.nikkeibp.co.jp/article/COLUMN/20070305/263828/
>本物のプログラマはHaskellを使う
>第8回 遅延評価の仕組み
>この問題を解決するのが必要呼び出しです。必要呼び出しでは,
>同じ変数から束縛された項はポインタによって共有され,
>一度簡約された項をもう一度使用する場合には最初の計算によってキャッシュされた解を利用します。
>項を共有することにより,構文はもはや通常の木構造ではなくグラフ(graph)構造を取ることになります。
>そのため,このような簡約方法を「グラフ簡約(あるいはグラフ簡約法,graph reduction)」と呼びます。
>また,同じ式の評価のために,キャッシュされた解を使う手法のことを「メモ化(memoization)」といいます。
>本物のプログラマはHaskellを使う
>第8回 遅延評価の仕組み
>この問題を解決するのが必要呼び出しです。必要呼び出しでは,
>同じ変数から束縛された項はポインタによって共有され,
>一度簡約された項をもう一度使用する場合には最初の計算によってキャッシュされた解を利用します。
>項を共有することにより,構文はもはや通常の木構造ではなくグラフ(graph)構造を取ることになります。
>そのため,このような簡約方法を「グラフ簡約(あるいはグラフ簡約法,graph reduction)」と呼びます。
>また,同じ式の評価のために,キャッシュされた解を使う手法のことを「メモ化(memoization)」といいます。
817デフォルトの名無しさん
2017/08/10(木) 11:53:35.98ID:Mbfm9qrf 共通部分式削除か
もしバグの原因が最適化だったら簡単だな
最適化を無効にするだけでわかる
もしバグの原因が最適化だったら簡単だな
最適化を無効にするだけでわかる
818デフォルトの名無しさん
2017/08/10(木) 15:16:55.85ID:7Zrve9l8 共通部分式削除ではないしバグでもない
819デフォルトの名無しさん
2017/08/10(木) 16:49:36.71ID:R2w5AQk8 ぼく、グラフ簡約がいつされていつされないのかよく解ってない(`・ェ・´)
820デフォルトの名無しさん
2017/08/10(木) 22:16:48.24ID:fh9/jf6h 基本的なこと
http://www.kotha.net/hperf/basics.html
> 関数の自動メモ化はない
> Haskellの関数は同じ引数で呼ぶと同じ結果を返すので透過的にメモ化が可能だが、GHCはそれを行わない。
> 局所的な最適化によってメモ化と同じ結果になることはあるが、一般には期待できない。
> メモ化が必要なら「引数->結果」の対応を保存するデータ構造(Map、Arrayなど)を明示的に用意する必要がある。
http://www.kotha.net/hperf/basics.html
> 関数の自動メモ化はない
> Haskellの関数は同じ引数で呼ぶと同じ結果を返すので透過的にメモ化が可能だが、GHCはそれを行わない。
> 局所的な最適化によってメモ化と同じ結果になることはあるが、一般には期待できない。
> メモ化が必要なら「引数->結果」の対応を保存するデータ構造(Map、Arrayなど)を明示的に用意する必要がある。
821デフォルトの名無しさん
2017/08/10(木) 22:27:51.24ID:fh9/jf6h GHCのこと
http://www.kotha.net/hperf/ghc.html
> プログラムの低水準の振る舞い(たとえば、「このループでメモリ確保は発生する?」「この式はどのタイミングで評価される?」)を理解したり、GHCの最適化の結果を見たりするのには、Core言語形式の中間出力を読むと良い。
> 特に、小さいループを可能な限り高速化したい場合など、最適化後のCore出力を比較しながらコードをいじるのが有効なことがある。
> Core形式の最終形(最適化された後、STG言語に変換される直前)は-ddump-prepで読める。
http://www.kotha.net/hperf/ghc.html
> プログラムの低水準の振る舞い(たとえば、「このループでメモリ確保は発生する?」「この式はどのタイミングで評価される?」)を理解したり、GHCの最適化の結果を見たりするのには、Core言語形式の中間出力を読むと良い。
> 特に、小さいループを可能な限り高速化したい場合など、最適化後のCore出力を比較しながらコードをいじるのが有効なことがある。
> Core形式の最終形(最適化された後、STG言語に変換される直前)は-ddump-prepで読める。
822デフォルトの名無しさん
2017/08/10(木) 23:42:17.05ID:7Zrve9l8 >>820
http://www.kotha.net/hperf/basics.html
Haskellの言語仕様(ja)は式の評価順序を定めていないが、
GHCを始めとする有名な処理系は全て「必要呼び(call by need)」という評価戦略を基本にしている。
必要呼び戦略のもう一つの特徴は引数の自動メモ化である。
ある関数の仮引数が、その関数の本体に複数回出現したとしても、対応する実引数の評価は高々一回しか発生しない。
http://www.kotha.net/hperf/basics.html
Haskellの言語仕様(ja)は式の評価順序を定めていないが、
GHCを始めとする有名な処理系は全て「必要呼び(call by need)」という評価戦略を基本にしている。
必要呼び戦略のもう一つの特徴は引数の自動メモ化である。
ある関数の仮引数が、その関数の本体に複数回出現したとしても、対応する実引数の評価は高々一回しか発生しない。
823デフォルトの名無しさん
2017/08/11(金) 00:45:37.86ID:Ze2QVHug 困ったときはhaskell-masterことtanakhに助けを求める
824デフォルトの名無しさん
2017/08/11(金) 03:54:12.02ID:7orZPIZ6 フィボナッチ数を漸化式で単に実装したとき、そのままだと深い部分で同じ引数による呼び出しが無数に発生してると思うんですが
自動メモ化してくれないんすね
自動メモ化してくれないんすね
825デフォルトの名無しさん
2017/08/11(金) 04:15:27.98ID:L7AEIGon826デフォルトの名無しさん
2017/08/11(金) 05:49:13.91ID:ZqUin61F 言語別平均年収ランキング
1位Scala 626万円
2位Python 601万円
3位Kotlin 577万円
4位Swift, Ruby 562万円
6位Java 552万円
7位Perl 551万円
8位 C言語 538万円
9位JavaScript 536万円
10位PHP 522万円
11位COBOL 509万円
以下は求人が少ないためランキングから除外
Groovy 680万円
Haskell 670万円
Erlang 604万円
LISP 581万円
尚、C++, C#は調査対象外とする
1位Scala 626万円
2位Python 601万円
3位Kotlin 577万円
4位Swift, Ruby 562万円
6位Java 552万円
7位Perl 551万円
8位 C言語 538万円
9位JavaScript 536万円
10位PHP 522万円
11位COBOL 509万円
以下は求人が少ないためランキングから除外
Groovy 680万円
Haskell 670万円
Erlang 604万円
LISP 581万円
尚、C++, C#は調査対象外とする
827デフォルトの名無しさん
2017/08/11(金) 10:48:20.88ID:Ca8C76qb828デフォルトの名無しさん
2017/08/11(金) 10:55:08.08ID:mLIKyCPo 難しすぎて習得者が少なすぎて調査不能なんだろう
829デフォルトの名無しさん
2017/08/11(金) 11:06:36.65ID:QQDjRimB 求人数が少ないから除外?
どうしてもその言語じゃなきゃだけど、その言語使える人が少ないって方が給料良いんだが。
(あと金出す側の資金力にもよる)
Fortranとか意外と良いぞ。
金融系なら関数型言語。
どうしてもその言語じゃなきゃだけど、その言語使える人が少ないって方が給料良いんだが。
(あと金出す側の資金力にもよる)
Fortranとか意外と良いぞ。
金融系なら関数型言語。
830デフォルトの名無しさん
2017/08/11(金) 11:07:39.31ID:QQDjRimB あ、Fortranは大学がスパコンで使うとかの場合ね。
831デフォルトの名無しさん
2017/08/11(金) 11:15:12.10ID:07jWFZnC いやC++C#は多いだろうよ
832デフォルトの名無しさん
2017/08/11(金) 11:32:50.22ID:eQbA+Atw なぜ 828 がジョークだと分からないんだw
831 も 829 にマジレスするなら、828 がジョークだと教えないと
(まさか 831 は 828 に対してのレスってことはないよね?)
831 も 829 にマジレスするなら、828 がジョークだと教えないと
(まさか 831 は 828 に対してのレスってことはないよね?)
833デフォルトの名無しさん
2017/08/11(金) 14:56:02.48ID:0Mux6fCC >>826の元記事はこれ
プログラミング言語別の平均年収ランキング、1位は「Scala」 - ITmedia NEWS
http://www.itmedia.co.jp/news/articles/1708/10/news073.html
プログラミング言語別の平均年収ランキング、1位は「Scala」 - ITmedia NEWS
http://www.itmedia.co.jp/news/articles/1708/10/news073.html
834デフォルトの名無しさん
2017/08/11(金) 20:01:49.81ID:rgIYrPBr グラフ簡約で物理同値が保証されてることを「メモ化」とはいわなくない?
835デフォルトの名無しさん
2017/08/11(金) 20:33:13.01ID:o2mcpSct836デフォルトの名無しさん
2017/08/11(金) 21:13:47.87ID:eQbA+Atw メモ化って memorization の訳だと思ってたが、 memoization という造語(1968年初出)の訳だったのか
んで、メモ化は簡約結果が同値であることを利用して、
計算結果を使いまわす研究での用語だったみたいね
ttps://ja.wikipedia.org/wiki/メモ化
んで、メモ化は簡約結果が同値であることを利用して、
計算結果を使いまわす研究での用語だったみたいね
ttps://ja.wikipedia.org/wiki/メモ化
837デフォルトの名無しさん
2017/08/12(土) 00:24:09.94ID:yWjB6ujN Haskell でのデバッグ - あどけない話
http://d.hatena.ne.jp/kazu-yamamoto/20120606/1338957783
http://d.hatena.ne.jp/kazu-yamamoto/20120606/1338957783
838デフォルトの名無しさん
2017/08/12(土) 19:28:27.04ID:G1Oa8HnK839デフォルトの名無しさん
2017/08/12(土) 21:06:06.85ID:vdGf/ex1 参照透明性を利用する
一度評価したらもう動かないのだという性質を利用するのだ
コンテナと組み合わせてほら!
一度評価したらもう動かないのだという性質を利用するのだ
コンテナと組み合わせてほら!
840デフォルトの名無しさん
2017/08/12(土) 22:47:13.92ID:zuB4Y/rr >>838
trace関数のソースにこう書かれてた
The 'trace' function should /only/ be used for debugging, or for monitoring
execution. The function is not referentially transparent: its type indicates
that it is a pure function but it has the side effect of outputting the
trace message.
他の関数と同様に考えるわけにはいかないようだ
trace関数のソースにこう書かれてた
The 'trace' function should /only/ be used for debugging, or for monitoring
execution. The function is not referentially transparent: its type indicates
that it is a pure function but it has the side effect of outputting the
trace message.
他の関数と同様に考えるわけにはいかないようだ
841デフォルトの名無しさん
2017/08/13(日) 00:48:15.11ID:SYaWjJhn Python, Kotlin, underscore.js にも、memoize がある
ナップサック問題で、使う
ナップサック問題で、使う
842デフォルトの名無しさん
2017/08/13(日) 01:44:46.49ID:Pg7jRQiA Let vs. Where - HaskellWiki
https://wiki.haskell.org/Let_vs._Where#Lambda_Lifting
これってwhereは引数に変換されるってこと?(英語うまく訳せなくて分からない)
https://wiki.haskell.org/Let_vs._Where#Lambda_Lifting
これってwhereは引数に変換されるってこと?(英語うまく訳せなくて分からない)
843デフォルトの名無しさん
2017/08/13(日) 06:26:42.63ID:BxbLY5/X 競技プログラミングではデフォルトライブラリしか使えないので
高度なアルゴリズムは自分で勉強して実装しておいたものをコピペするしかないのだ
高度なアルゴリズムは自分で勉強して実装しておいたものをコピペするしかないのだ
844デフォルトの名無しさん
2017/08/13(日) 10:34:38.57ID:fRo9GRp1 モナドってなんなの?
845デフォルトの名無しさん
2017/08/13(日) 12:11:08.44ID:ndxDWak1 文脈
846デフォルトの名無しさん
2017/08/13(日) 13:12:26.05ID:mWeUlEpW 山本タソは「裏面配線」って言ってたかな
847デフォルトの名無しさん
2017/08/13(日) 17:47:54.48ID:fRo9GRp1 関数プログラミングって文字列型って上手くあつかえるの?
オブジェクト指向の最大の欠点って「文字列を上手く扱えない」ところに
あると思うんだよね。
オブジェクト指向の最大の欠点って「文字列を上手く扱えない」ところに
あると思うんだよね。
848デフォルトの名無しさん
2017/08/13(日) 17:51:31.77ID:fRo9GRp1849デフォルトの名無しさん
2017/08/13(日) 19:22:11.54ID:zbgzOget >>842
違うよ。
ある関数の定義に使う補助的な関数の定義は、独立してトップレベルに置く事もできるし、
let や where を使って関数定義の中に置く事もできるよ、って言ってる。
関数内部で定義されていた関数を外に出して独立させることを lambda lifting と言って、
逆に外にあった関数を別の関数の内部で定義することを lambda dropping と言うんだ。
Haskell を使うだけならこんな理解で十分なんだけど、
もともとは関数型言語の処理系の研究で出てきた用語なんで、
その辺りまで深く学びたいのなら、やつぱり英語を読めないと難しいかも。
ちなみに、そのリンク先の [3 Lambda Lifting] と比べれば、
その直後の [4 Problems with where] の方が衝撃的な内容だね。
Haskell を実用的に使っている人にとってはこっちの方が大事な内容だよ。
違うよ。
ある関数の定義に使う補助的な関数の定義は、独立してトップレベルに置く事もできるし、
let や where を使って関数定義の中に置く事もできるよ、って言ってる。
関数内部で定義されていた関数を外に出して独立させることを lambda lifting と言って、
逆に外にあった関数を別の関数の内部で定義することを lambda dropping と言うんだ。
Haskell を使うだけならこんな理解で十分なんだけど、
もともとは関数型言語の処理系の研究で出てきた用語なんで、
その辺りまで深く学びたいのなら、やつぱり英語を読めないと難しいかも。
ちなみに、そのリンク先の [3 Lambda Lifting] と比べれば、
その直後の [4 Problems with where] の方が衝撃的な内容だね。
Haskell を実用的に使っている人にとってはこっちの方が大事な内容だよ。
850デフォルトの名無しさん
2017/08/13(日) 20:15:07.01ID:DrQ+cSjE Haskellという土台の上に、オレオレ言語を構築する。それがモナドだ
Haskell上で動作する『ぼくのかんがえたさいきょうのげんご』
DSLプラットフォーム
Haskell上で動作する『ぼくのかんがえたさいきょうのげんご』
DSLプラットフォーム
851デフォルトの名無しさん
2017/08/13(日) 20:19:51.10ID:qvBBF+tW >>849
衝撃だけど実際どれくらいパフォーマンス上のインパクトがあるの?
衝撃だけど実際どれくらいパフォーマンス上のインパクトがあるの?
852デフォルトの名無しさん
2017/08/13(日) 21:59:10.19ID:zbgzOget >>851
試せばすぐに分かるが、あのフィボナッチ数のサンプルでは全く大した事なかったりする。
確かに後者の方が遅い代わりにメモリ効率いいけど、ほとんど差が出ない事に驚くほどだよ。
差がはっきり出る例を作る方が難しいと思う。
衝撃なのはパフォーマンスの差じゃなくて、単に引数を省略しただけで
コンパイルの結果に差が出ることがある、という事実。
GHCにはこういうことがあると、頭の片隅にでも入れておいた方がいいね。
他にも「単に***を変えただけで何で意図したように動かないの?」
ってなるようなコンパイラの仕様があるだろうから、
それに出くわした時に、もしかしてと気づければ無駄に悩む時間が省ける。
試せばすぐに分かるが、あのフィボナッチ数のサンプルでは全く大した事なかったりする。
確かに後者の方が遅い代わりにメモリ効率いいけど、ほとんど差が出ない事に驚くほどだよ。
差がはっきり出る例を作る方が難しいと思う。
衝撃なのはパフォーマンスの差じゃなくて、単に引数を省略しただけで
コンパイルの結果に差が出ることがある、という事実。
GHCにはこういうことがあると、頭の片隅にでも入れておいた方がいいね。
他にも「単に***を変えただけで何で意図したように動かないの?」
ってなるようなコンパイラの仕様があるだろうから、
それに出くわした時に、もしかしてと気づければ無駄に悩む時間が省ける。
853デフォルトの名無しさん
2017/08/13(日) 22:05:27.98ID:IBmKuvX6 STモナドとSTArrayの理解を深めるのに向いてる書籍やサイトなどがあれば英語でもいいので教えていただきたいです
競技プログラミングで少し行き詰まってて
競技プログラミングで少し行き詰まってて
854デフォルトの名無しさん
2017/08/13(日) 22:12:47.72ID:qvBBF+tW855デフォルトの名無しさん
2017/08/13(日) 22:35:47.24ID:3dVRXwBQ >>851
fib1 40は1秒かからなかったけど
fib2 40だと37秒かかった
fib1 = (map fib1' [0 ..] !!)
where
fib1' 0 = 0
fib1' 1 = 1
fib1' n = fib1 (n - 1) + fib1 (n - 2)
fib2 x = map fib2' [0 ..] !! x
where
fib2' 0 = 0
fib2' 1 = 1
fib2' n = fib2 (n - 1) + fib2 (n - 2)
fib1 40は1秒かからなかったけど
fib2 40だと37秒かかった
fib1 = (map fib1' [0 ..] !!)
where
fib1' 0 = 0
fib1' 1 = 1
fib1' n = fib1 (n - 1) + fib1 (n - 2)
fib2 x = map fib2' [0 ..] !! x
where
fib2' 0 = 0
fib2' 1 = 1
fib2' n = fib2 (n - 1) + fib2 (n - 2)
856デフォルトの名無しさん
2017/08/13(日) 22:42:29.03ID:3dVRXwBQ857デフォルトの名無しさん
2017/08/13(日) 22:56:30.39ID:Pg7jRQiA >>849
教えてくれてありがとう
教えてくれてありがとう
858デフォルトの名無しさん
2017/08/13(日) 23:03:01.35ID:Kt+T0SXe 毎回 let 束縛し直すから遅い、って凄えなこれ
手動 eta-reduction 必須、みたいなんか
手動 eta-reduction 必須、みたいなんか
859デフォルトの名無しさん
2017/08/13(日) 23:18:59.79ID:AxVfgjdD >>855
fib3 40、fib4 40は fib2 40と同じくらい
fib3 =
let fib3' 0 = 0
fib3' 1 = 1
fib3' n = fib3 (n - 1) + fib3 (n - 2)
in (map fib3' [0 ..] !!)
fib4 x =
let fib4' 0 = 0
fib4' 1 = 1
fib4' n = fib4 (n - 1) + fib4 (n - 2)
in map fib4' [0 ..] !! x
fib3 40、fib4 40は fib2 40と同じくらい
fib3 =
let fib3' 0 = 0
fib3' 1 = 1
fib3' n = fib3 (n - 1) + fib3 (n - 2)
in (map fib3' [0 ..] !!)
fib4 x =
let fib4' 0 = 0
fib4' 1 = 1
fib4' n = fib4 (n - 1) + fib4 (n - 2)
in map fib4' [0 ..] !! x
860デフォルトの名無しさん
2017/08/13(日) 23:39:51.65ID:DrQ+cSjE >>842
なにこれこわい
なにこれこわい
861デフォルトの名無しさん
2017/08/14(月) 00:09:46.90ID:CgEdc2Wx■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 「日本はパンダがいなくなる状況に直面するだろう」 中国メディア、専門家の見方伝える [♪♪♪★]
- ネット殺到「高市総理の責任」「完全に高市リスク」「負けるな」中国が水産物輸入停止→流石に総理批判の声も「どう責任取る?」 ★11 [樽悶★]
- 止まらぬ「日本売り」 高市財政への懸念で進む金利上昇と円安 ★2 [蚤の市★]
- ネット殺到「高市総理の責任」「完全に高市リスク」「負けるな」中国が水産物輸入停止→流石に総理批判の声も「どう責任取る?」 ★12 [樽悶★]
- 【無言】中国怒らせた高市首相→1週間だんまり、国民に実害も説明なし 中国問題を避けてスルー… ★5 [BFU★]
- 外国人の犯罪率は日本人の1.72倍 警察庁が短期滞在者除いた数字を参院内閣委で答弁★2 [七波羅探題★]
- 🏡
- 【高市悲報】大暴落 [115996789]
- 【速報】東京から人が消える [329329848]
- 【悲報】無能ぼく、仕事では「どうやったら楽できるか」を最優先に考えてしまうwwwwww
- 友達がお前らの事をさ…
- 【画像】おじさん起きる、そして鹿と会う
