haskell-jp / questions #50

ああ失礼。私も今Settingsに到達しました.
GhcMonadのgetSessionDynFlagsかな
このコードをかっこよくするにはどのようにすればいいのでしょうか?
all isJust でチェックしてから map fromJust しているところなどがとてもダサく感じています。
>>= を繋げるみたいな感じでかっこよく書きたいです。
よろしくお願い致します。
あーいえ,問題になるわけじゃなく今パフォーマンスチューニングするためにコンパイラの最適化がどうなってるかイチから調べているところなだけです.ありがとうございます.
おっと、途中で values が増えてたので期待する動作がわからなく……
説明不足ですみません!
keys、もしくはvaluesに一つでもNothingが入っていたらNothingを返したいんです
foo xs ys = sequenceA $ zipWith f xs ys
where
f mx my = do { x <- mx; y <- my; return (x, y) }
これでどうでしょ?
get :: [Maybe a] -> Maybe [a]
get = undefined

some :: [Maybe Char] -> [Maybe Int] -> Maybe (Map Char Int)
some keys values = do
    k <- get keys
    v <- get values
    return Map.fromList $ zip k v
λ> keys
[Just "a",Just "b",Nothing]
λ> values
[Just 1,Just 2,Just 3]
λ> foo keys values
Nothing
λ> keys
[Just "a",Just "b",Just "c"]
λ> values
[Just 1,Just 2,Just 3]
λ> foo keys values
Just [("a",1),("b",2),("c",3)]
こうなる.
codeどうやって貼り付けるんだ (じじぃまるだし
とりあえず、"```"で囲む。
mdキホーでしたか.
foo xs ys = sequenceA $ zipWith f xs ys
  where
    f mx my = do { x <- mx; y <- my; return (x, y) }
cutsea110さんの fliftA2 (,) で書けば1行で行ける
おおステキ
あ、ちがうちがう. fのコンテキストはMaybeなのでmxやmyはJust 1とかNothing.
liftA2したら直積作っちゃうな.
す、すごい…!
みなさんありがとうございます!
こんなにかっこよく書けるんですね!!(見たことない関数がある…seequenceA…)
オリジナルのコードが一番分かりやすいので、変にかっこよく書く必要はないと思いますよ。
sequenceAはsequenceで良さげ.
そりゃそうだ。
リストが長く効率を求めるなら、再帰で書くといいでしょう。
確かにオリジナルは一番分かりやすいですね!
自分はこうなった。確かにかずさんのいうとおり、これだと長いリストだと危ない。
some :: [Maybe String] -> [Maybe Int] -> Maybe (M.Map String Int)
some keys values = do
    k <- sequence keys
    v <- sequence values
    return $ M.fromList $ zip k v

確かに、allとfromListでリストを二回参照するとスペースリークするので、zip(With)でくっつけてから回すか再帰で2つのリストを同時にマッチしないとダメなのには注意です
おお!こちらはわかりやすいのにかっこいいですね!
GhcMonadって単にGHCを起動して指定された場所のsettingsファイルを読みに行く実装しかなくないですか?
多相にするとこうなる

some :: (Ord key) => [Maybe key] -> [Maybe value] -> Maybe (M.Map key value)
some keys values = do
    k <- sequence keys
    v <- sequence values
    return $ M.fromList $ zip k v

2回参照するだけでもスペースリークって発生してしまうのですか…知りませんでした・・・
これのREADMEの解説が分かりやすいです>リーク http://hackage.haskell.org/package/foldl
熟読します…!
リストが長いと危ないというのはsequenceが原因ということですか??
レベルが低く皆さんの会話についていけず…質問ばかりですみません…
リストの長さが同じことが仮定できるなら
fmap M.fromList $ zipWithM (liftA2 (,)) keys values

でもいいですね
sequence, sum, foldr, allとかの「リストを全部なめる関数」は、1回だけ呼ぶ分には遅延評価で上手いこと「生成→消費」のループを回して、余計なメモリを使わずに処理できるんですが、
この類の関数を2回以上呼んでしまうと、生成した要素を捨てずに覚えておかないといけないので、リストの長さ分のメモリを使ってしまうんですね
(さっきのページそれほど親切に書いてないですね、所詮ライブラリの説明なので)
なるほど…知りませんでした…!!
@autotaker おお!そんな書き方もできるんですね!!
先程のリンクを見ているのですが ( http://hackage.haskell.org/package/foldl )
sumAndLength xs = (sum xs, length xs)
これを見るとlength xsが終わった段階でxsは必要なくなってガベージコレクトの対象になるように見えるのですが、実際は違うのはなぜなのでしょうか?
あ、length xsが終わったらxsは必要なくなるけどsum xsの実行時点では次のlength xsがあるからxsを捨てられないということですか?
なるほど!!
なんとなくわかったようなわかってないような…
それとリストが長いと危険というのはどう関係するのでしょうか?
長いリストを持っている時点でメモリ上に長いリストが展開されているわけではないのでしょうか?
長いリストを持っている時点でメモリ上に長いリストが展開されている
それはその通りです。
問題になるのは、たとえばkeysが

let keys = [Just (show n )| n <- [1..] ]


のようにメモリに展開されていない状態で処理を始める場合なので、結構限られたケースかもしれません。
今回のケースでは最終的にできる M.Map String IntがO(n)のメモリを消費するのであまり気にしなくてもいい気がします。
>リストの長さが同じことが仮定できるなら
この仮定は必要なのでしょうか? zipシリーズは長さがずれているなら短い方に合わせて処理しそうですが…
一番始めのコードの場合、長い方のリストの末尾にNothingが入っててもNothingになるので、厳密にいうと動きが違うんですよね……
ああなるほど
危険という表現は微妙だったかもしれない!
今回の場合なら、2つのリストを同時に辿ったほうが効率いいんじゃないかなーって