3

だから私は厳密なマップを持っています

import qualified Data.Map.Strict      as Map
import qualified Data.ByteString       as BS
import qualified Data.ByteString.Char8 as C

type Key = Int
type Value = BS.ByteString

data KeyValue = KeyValue !(Map.Map Key Value)

source :: [(Key, Value)]
source = zip [0..] $ map (\x -> BS.concat $ replicate 10000 $ "alsfdd" `C.append` (C.pack $ show x)) [0..10000]

要素を配置するたびにマップを評価しようとしています...

 putStrLn "Putting 10000 Strict ByteStrings into a Map"
 let newMap = foldr (\(k,v) i -> Map.insert k v $! i) Map.empty source
 putStrLn "Done..."
 putStrLn "Launching interactive mode"
 forever $ do
      putStrLn "Enter an integer:"
      k <- getLine
      print $ Map.lookup (read k) newMap

ただし、「対話モード」になってクエリを送信するまで、マップは評価されません。

評価できる唯一の方法は、そのサイズを出力することです。

newMap <- foldM (\i (k, v) -> (print $ Map.size i) >> (return Map.insert k v i)) Map.empty source

seqまたは$!正しく使用するにはどうすればよいですか?

これが基づいている私の実際の問題の詳細:

元のプログラムでは、Map は TVar に含まれており、要素は IO イベントに挿入されていることに注意してください。したがって、TVar haskell を変更している場合、マップの評価が強制されない理由がわかりません。私のプログラムは、1 つのアドレスが検索を実行する「リーダー」であるマルチスレッド ソケット サーバーです。もう一方のソケット アドレスは、バイト文字列をマップにプッシュするだけです。差し込み口にソケットを2つ、リーダーにソケットを1つ接続できます。何度も挿入すると、リーダーソケットが値を検索するまでマップは評価されません。TVar を変更するときに Map を評価したいと思います。これを行う唯一の方法は、挿入物で TVar を変更する前にマップのサイズを印刷することです。

編集:

そこで、上記の例では機能する bang パターンを試しましたが、私のサーバーでは機能しません。

buildIndex :: Int -> ByteString -> M.Map Int ByteString -> M.Map Int ByteString

liftIO $ do indexed <- readTVarIO tvi
            let !newIndex = buildIndex nextKey serialized indexed
            atomically $ writeTVar tvi $! newIndex
4

2 に答える 2

0

どうですか:

liftIO $ atomically $ modifyTVar' (buildIndex nextKey serialized) tvi

それ以外の

liftIO $ do indexed <- readTVarIO tvi
         let !newIndex = buildIndex nextKey serialized indexed
         atomically $ writeTVar tvi $! newIndex

modifyTVar'のドキュメントを参照してください。また、弱い頭の正規形とは何ですか?

于 2013-08-30T17:08:38.543 に答える