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">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 class="h5">&lt;<a href="mailto:haskell.vivian.mcphail@gmail.com">haskell.vivian.mcphail@gmail.com</a>&gt; wrote:<br>
&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">lrpalmer@gmail.com</a>&gt;<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>