This is just a comment. I figured I would get rid of the tuple argument (adjusting the use of append
in gridWalk
), but the result is that (only) the last Int argument has to be bang'd to get everything unboxed, which does seem strange:
append :: Snakev s -> Int -> Int -> Int -> Int -> ST s (Snakev s)
append (S i v) a b c !d = do
if i < len then do MU.unsafeWrite v i (a,b,c,d)
return $ S (i+1) v
else do y <- MU.unsafeGrow v additional
MU.unsafeWrite y i (a,b,c,d)
return $ S (i+1) y
where len = MU.length v
additional = floor (1.5 * int2Float len) -- this seems kind of bizarre
-- by the way; can't you stay inside Int?
-- 3 * (len `div` 2) or something
Edit, also, you get everything unboxed if you move the application of S (i+1)
outside the do block, but I'm not sure if that gets us closer to the quarry...:
append :: Snakev s -> Int -> Int -> Int -> Int -> ST s (Snakev s)
append (S i v) a b c d = do
if i < len then liftM (S (i+1)) $ do MU.unsafeWrite v i (a,b,c,d)
return v
else liftM ( S (i+1)) $ do y <- MU.unsafeGrow v zzz
MU.unsafeWrite y i (a,b,c,d)
return y
where len = MU.length v
zzz = floor (1.5 * int2Float len)
But if liftM
is replaced by fmap
we are back to the lone unboxed in. Things go well if liftM (S (1+i)
or fmap (S (i+1)
is moved all the way out to the front:
append (S i v) a b c d = S (i+1) <$> do ...