
On Tue, Oct 04, 2016 at 06:19:52PM +0100, Tom Ellis wrote:
On Tue, Oct 04, 2016 at 01:51:04PM +0200, Zoran Bosnjak wrote:
can you please explain why does this simple program leak memory.
But, if I replace loop2 with loop1 (that is: without using "forever"), then it does not leak.
import Control.Concurrent import Control.Monad import Control.Monad.Trans import Control.Monad.Trans.Reader import Control.Monad.Trans.State
main :: IO () main = do --let loop1 = (liftIO $ threadDelay 1) >> loop1 let loop2 = forever (liftIO $ threadDelay 1)
_ <- runStateT (runReaderT loop2 'a') 'b' return ()
My results below. Looks like there's something wrong with *> for ReaderT and StateT.
This seems to be how it executes let loop = return () *> loop in loop in runReaderT loop () let loop = return () *> loop in loop in loop () let loop = (id <$ return ()) <*> loop in loop in loop () -- <*> for ReaderT in terms of <*> for m let loop = \r -> (id <$ return ()) r <*> loop r in loop in loop () let loop = \r -> (id <$ return ()) r <*> loop r in loop in (id <$ return ()) () <*> loop () let loop = \r -> (id <$ return ()) r <*> loop r in loop in ((fmap . const) id (return ())) () (loop ()) let loop = \r -> (id <$ return ()) r <*> loop r in loop in (fmap (const id) (return ())) () <*> loop () -- fmap for ReaderT m in terms of fmap for m let loop = \r -> (id <$ return ()) r <*> loop r in loop in (fmap (const id) . (return ())) () <*> loop () let loop = \r -> (id <$ return ()) r <*> loop r in loop in (\x -> fmap (const id) (return () x)) () <*> loop () let loop = \r -> (id <$ return ()) r <*> loop r in loop in fmap (const id) (return () ()) <*> loop () -- return for ReaderT in terms of return for m let loop = \r -> (id <$ return ()) r <*> loop r in loop in fmap (const id) (return ()) <*> loop () which then in IO I think becomes fmap (const id ()) (loop ()) so each time round the loop we add a redundant fmap (const id ()) on the front. Oh dear. Something needs fixing. I'm not sure what. We don't see the space leak in the Identity Applictave because fmap (const id) (return ()) <*> loop () is const id (return ()) (loop ()) which evaluates as (\x y -> x) id (return ()) (loop ()) id (loop ()) loop () Anyone who is at Haskell eXchange on Thursday and who is interested in working out how the above code executes can come to my talk! Tom