<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>And just because this has not been explicitly stated: it's not just for aesthetic reasons that you couldn't do this with a pure function, but because it violates the semantics and gets you the wrong result. So for example, if you modified Tim's code to be</div><div><br></div><div><br></div><div><div><div>import Data.IORef</div><div>import System.IO.Unsafe</div><div><br></div><div>mkNext :: (Num a) => IO a</div><div>mkNext = do</div><div> ref <- newIORef 0</div><div> return . unsafePerformIO $</div><div> do</div><div> modifyIORef ref (+1)</div><div> readIORef ref</div><div><br></div><div>main :: IO ()</div><div>main = do</div><div> foo <- mkNext</div><div> print foo</div><div> print foo</div><div> print foo</div><div><br></div></div><div><br></div><div>Then the output that you will see (with GHC at least) is</div><div><br></div><div>1</div><div>1</div><div>1</div><div><br></div><div>because the compiler assumes that it only needs to evaluate foo once, after which it can cache the result due to assumed referential transparency.</div><div><br></div><div>- Greg</div><div><br></div><div><br></div><div><br></div></div><div><div>On Oct 21, 2009, at 11:40 AM, Tim Wawrzynczak wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">True...here we go then:<br><br>import Data.IORef<br>import System.IO.Unsafe<br><br>mkNext :: (Num a) => IO (IO a)<br>mkNext = do<br> ref <- newIORef 0<br> return (do modifyIORef ref (+1)<br> readIORef ref)<br> <br>next :: IO ()<br>next = do<br> foo <- mkNext<br> a <- sequence [foo,foo,foo]<br> putStrLn $ show a<br><br><br>running next will print [1,2,3] which is the result of calling 'foo' 3 times.<br><br>But technically then, mkNext is just an IO action which returns an IO action ;)<br> and not a function which will return the next value each time it is called,<br>hence the need to extract the value from mkNext, then use it...<br><br>Cheers,<br>Tim<br><br><br><div class="gmail_quote">On Wed, Oct 21, 2009 at 1:30 PM, minh thu <span dir="ltr"><<a href="mailto:noteed@gmail.com">noteed@gmail.com</a>></span> wrote:<br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">2009/10/21 Tim Wawrzynczak <<a href="mailto:inforichland@gmail.com">inforichland@gmail.com</a>><br> <div class="im">><br> > Here's an example in the IO monad:<br> ><br> > import Data.IORef<br> > import System.IO.Unsafe<br> ><br> > counter = unsafePerformIO $ newIORef 0<br> ><br> > next = do<br> > modifyIORef counter (+1)<br> > readIORef counter<br> ><br> > Naturally, this uses unsafePerformIO, which as you know, is not kosher...<br> <br> </div>But you don't close around the Ref like in your schemy example.<br> <br> mkNext = do<br> ref <- newIORef 0<br> return (do modifyIORef ref succ<br> readIORef ref)<br> <br> mimic your other code better.<br> <br> Cheers,<br> <font color="#888888">Thu<br> </font></blockquote></div><br> _______________________________________________<br>Haskell-Cafe mailing list<br><a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br></blockquote></div><br></body></html>