Hi, Alexander<br><br>Here&#39;s my take on why the code isnt &quot;right&quot;: <br><br>In the &quot;let&quot; the &quot;v1&quot; and &quot;v2&quot; get lazyly bound to code that calls unsafePerformIO. unsafePerformIO does side-effectful things, but works outside the IO monad and thus outside the main order of IO actions. <br>
<br>If you create a buffer, push something in and make two lists of it -- &quot;v1&quot; and &quot;v2&quot; -- then they don&#39;t get evaluated to concrete lists (weak head normal form?) right away, but when they are actually needed. So if you print &quot;v1&quot;, &quot;buf&quot; is read and converted into a list (and printed). &quot;v2&quot; stays unevaluated, but bound to the value of &quot;buf&quot;. So if you change &quot;buf&quot;, then &quot;v2&quot; is bound to be different too.<br>
<br>This breaks referential transperency because &quot;v1&quot; and &quot;v2&quot; by theire definitions should be exactly the same. And the breakage can only happen because of using unsafePerformIO, which allowes you to go out in the IO world and get stuff, but bypass the order of evaluation that IO monad forces you to otherwise have.<br>
<br><br>Someone correct me if I&#39;m wrong :)<br><br><br>--<br>Markus Läll<br><br><br><div class="gmail_quote">On Tue, Feb 15, 2011 at 8:08 AM, Alexander McPhail <span dir="ltr">&lt;<a href="mailto:haskell.vivian.mcphail@gmail.com">haskell.vivian.mcphail@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Hi list,<br><br>Could someone explain why the error pointed out by Luke occurred?<br><br><div class="gmail_quote">
From: <b class="gmail_sendername">Luke Palmer</b> <span dir="ltr">&lt;<a href="mailto:lrpalmer@gmail.com" target="_blank">lrpalmer@gmail.com</a>&gt;</span><br>
<br>I think this would be a very good question for the list.  Don&#39;t worry,<br>
they&#39;re nice helpful folks.<br>
<br>
On Mon, Feb 14, 2011 at 10:10 PM, Alexander McPhail<br>
<div><div></div><div><div class="im">&lt;<a href="mailto:haskell.vivian.mcphail@gmail.com" target="_blank">haskell.vivian.mcphail@gmail.com</a>&gt; wrote:<br></div>
&gt; Hi Roman,<br>
&gt;<br>

&gt;<br>
&gt; Can you explain why the following code doesn&#39;t work?  &#39;unsafePerformIO&#39; is<br>
&gt; used all the time in hmatrix.  For example, adding two vectors, we create a<br>
&gt; new Vector then use that as the target for an FFI C call.<br>
&gt;<br>
&gt; Is the difference because I&#39;m using mutable Storable Vectors?  I would have<br>
&gt; thought that unsafeFreeze (at the end) would make sure the problem reported<br>
&gt; by Luke wouldn&#39;t occur.<br>
&gt;<br>
&gt; Is there a problem with laziness in the let binding of Luke&#39;s example?<br>
&gt;<br>
&gt; I note that in Data.Vector.Storable there is a pure &#39;convert&#39; function,<br>
&gt; which is essentially what I am trying to emulate.<br>
&gt;<br>
&gt; -- | convert to a vector<br>
&gt; toVector :: Storable a =&gt; Buffer a -&gt; (V.Vector a)<br>
&gt; toVector (B o n v) = unsafePerformIO $ do<br>
&gt;    w &lt;- M.new n<br>
&gt;    i &lt;- readIORef o<br>
&gt;    M.unsafeWith v $ \p -&gt;<br>
&gt;        M.unsafeWith w $ \q -&gt; do<br>
&gt;          let n&#39; = n-i<br>
&gt;          copyArray q (p `advancePtr` i) n&#39;<br>
&gt;          if i /= 0<br>
&gt;             then copyArray (q `advancePtr` n&#39;) p i<br>
&gt;             else return ()<br>
&gt;    V.unsafeFreeze w<br>
&gt; {-# INLINE toVector #-}<br>
&gt;<br>
&gt;<br>
&gt; Vivian<br>
&gt;<br>

&gt; From: Luke Palmer &lt;<a href="mailto:lrpalmer@gmail.com" target="_blank">lrpalmer@gmail.com</a>&gt;<div class="im"><br>

&gt;<br>
&gt; This interface is an outlaw.<br>
&gt;<br>
&gt; main = do<br>
&gt;    buf &lt;- newBuffer 10 :: IO (Buffer Int)<br>
&gt;    pushNextElement buf 1<br>
&gt;    let v1 = V.toList (toVector buf)<br>
&gt;        v2 = V.toList (toVector buf)<br>
&gt;    print v1<br>
&gt;    pushNextElement buf 2<br>
&gt;    print v2<br>
&gt;<br>
&gt; Despite v1 and v2 being defined to equal the exact same thing, this<br>
&gt; program prints two distinct lines.<br>
&gt;<br>
&gt; toVector depends on the current state of the buffer.  If this is to be<br>
&gt; a law-abiding interface, toVector must return a value in IO:<br>
&gt;<br>
&gt;    toVector :: (Storable a) =&gt; Buffer a -&gt; IO (Vector a)<br>
&gt;<br>
&gt; Luke<br>
&gt;<br clear="all"></div></div></div></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" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br></blockquote></div><br>