stack overflow - nonobvious thunks?
I'm trying to write a function to build a table of values from a list. Here's my current attempt: table :: (Ord a) => [a] -> [(a,Int)] table xs = Map.assocs $! foldl' f Map.empty xs where f m x = Map.insertWith (+) x 1 m The ($!) and the foldl' were my clumsy attempts to avoid the stack overflows I keep getting, but it's not working right yet. If I set unif :: [Int] unif = randomRs (1,10) $ mkStdGen 1 then I should be able to use f :: Int -> [(Int, Int)] f n = table $ take n unif I would think this should work using very little memory, since unif is evaluated lazily, and the table is built eagerly. But I must be keeping around more thunks than I think, since I get (in ghci) *Main> f 1000000 [(1,99816),(2,100187),(3,99969),(4,99892),(5,100194),(6,100190),(7,99776 ),(8,100347),(9,100125),(10,99504)] *Main> f 10000000 [(1,*** Exception: stack overflow So it works on big lists, but not huge ones. What am I missing? Is there a way to do this other than just increasing the memory allocation? Thanks, Chad Scherrer
Scherrer, Chad wrote:
f m x = Map.insertWith (+) x 1 m
insertWith is inserting the "nonobvious thunks". Internally it applies (+) to the old value and the new one, producing a thunk. There is no place you could put a seq or something to force the result. You basically need insertWith', which isn't there. I think, your best best is to manually lookup the old value, combine with the new, force the result, then insert that, overwriting the old value. On top of that you still need foldl' to avoid building long chains of Map.insert. Udo. -- The Second Law of Thermodynamics: If you think things are in a mess now, just wait! -- Jim Warner
participants (2)
-
Scherrer, Chad -
Udo Stenzel