だから私は厳密なマップを持っています
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