<br><br>
<div class="gmail_quote">On Feb 6, 2008 1:18 AM, Jonathan Cast &lt;<a href="mailto:jonathanccast@fastmail.fm">jonathanccast@fastmail.fm</a>&gt; wrote:<br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">
<div style="WORD-WRAP: break-word">
<div>
<div class="Ih2E3d">
<div>On 5 Feb 2008, at 10:14 PM, Jeff φ wrote:</div><br>
<blockquote type="cite"><br><br>
<div class="gmail_quote">On Feb 5, 2008 4:58 PM, Chaddaï Fouché &lt;<a href="mailto:chaddai.fouche@gmail.com" target="_blank">chaddai.fouche@gmail.com</a>&gt; wrote:<br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">2008/2/5, Jeff φ &lt;<a href="mailto:jeff1.61803@gmail.com" target="_blank">jeff1.61803@gmail.com</a>&gt;:<br>

<div>&gt; This is interesting. &nbsp;I&#39;ve been programming in Concurrent Clean for a while.<br>&gt; &nbsp;Instead of monads, Clean supports unique types for mutable arrays and IO.<br>&gt; In Clean, I can write code that iterates through a mutable array by<br>
&gt; converting it to a lazy list. &nbsp;This is convenient because I can use all the<br>&gt; nice list processing functions that are available.<br>&gt;<br><br></div>You could absolutely write something like that in Haskell, but as some<br>
have pointed out, this is probably _not a Good Idea_, even though it<br>works in your particular case, the array could be modified between the<br>time you get the lazy list and the time you actually read it... And<br>there&#39;s no way to insure it&#39;s not happening in Haskell, and I strongly<br>
doubt there is in Concurrent Clean, could you confirm ?<br></blockquote>
<div>
<div>Concurrent Clean can handle this in a safe way.&nbsp; Here&#39;s a&nbsp;code snippet for normalize_2D_ary from ArrayTest.icl:</div></div></div>
<div class="gmail_quote">&nbsp;</div>
<div class="gmail_quote"><font face="courier new,monospace">uToList_2D :: *(a u:(b c)) -&gt; (.[c],*(a u:(b c))) | Array a (b c) &amp; Array b c<br>map_in_place_2d_arr :: (a -&gt; a) *(b *(c a)) -&gt; *(b *(c a)) | Array b (c a) &amp; Array c a<br>
</font></div>
<div class="gmail_quote"><font face="courier new,monospace">normalize_2D_ary :: *(a *(b c)) -&gt; *(a *(b c)) | Array a (b c) &amp; Array b c &amp; / c &amp; Ord c<br></font><font face="courier new,monospace">normalize_2D_ary ary =<br>
&nbsp;&nbsp;&nbsp; let (lst,ary2) = uToList_2D ary<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_elem = foldl1 max lst<br>&nbsp;&nbsp;&nbsp;&nbsp;in&nbsp; map_in_place_2d_arr (\ x -&gt; x / max_elem) ary2<br></font></div>
<div class="gmail_quote">uToList_2D takes a unique array, ary,&nbsp;and returns a tuple&nbsp;containing&nbsp;a list of the&nbsp;array elements&nbsp;and a &quot;new&quot; array, ary2.&nbsp; uToList_2D does not modify ary, but Clean&#39;s type system forces any function that accesses a unique array to thread the array through and return a &quot;new&quot; array.&nbsp; Under the hood the &quot;new&quot; array actually uses the same&nbsp;memory storage&nbsp;as the original array.&nbsp; So, it is&nbsp;effecient.&nbsp; Threading the array serializes access insuring&nbsp;the&nbsp;array won&#39;t be modified until the&nbsp;list is complete.&nbsp;</div>
</blockquote>
<div><br></div></div>
<div>I&#39;m confused --- does uToList_2D return the head of the list before or after it finishes reading the array? &nbsp;If before, then I don&#39;t see how the type system prevents me from modifying the array before I finish examining the list, as you claim. &nbsp;If after, then the list isn&#39;t truly lazy.</div>
</div></div></blockquote>
<div>&nbsp;</div>
<div>uToList_2D can return the head of the list before it finishes reading the array.&nbsp; I could modify the code so that it is ambiguous whether the array is modified before&nbsp;the list processing is&nbsp;finished.</div>
<div>&nbsp;</div>
<div><font face="courier new,monospace">normalize_2D_ary ary =<br>&nbsp;&nbsp;&nbsp; let (lst,ary2) = uToList_2D ary<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max_elem = foldl1 max lst<br>&nbsp;&nbsp;&nbsp;&nbsp; in&nbsp; map_in_place_2d_arr (\ x -&gt; x / max_elem) ary&nbsp; // I changed ary2 to ary</font></div>
<font face="courier new,monospace"></font></div>
<div class="gmail_quote"><font face="courier new,monospace">
<div>&nbsp;</div>
<div></div></font><font face="arial,sans-serif">However, the type system will generate an error with this code because ary&nbsp;is no longer unique because it is referenced in two expressions.&nbsp; Clean produces this error message:</font></div>

<div>&nbsp;</div>
<div>Uniqueness error [ArrayTest.icl,55,normalize_2D_ary]: &quot;ary&quot; demanded attribute cannot be offered by shared object</div>
<div>&nbsp;</div>
<div>I should mention that&nbsp;a&nbsp;problem with the code I&#39;ve shown is that it is very sensitive to the order in which the expression graph is evaluated.&nbsp; Simple changes can cause lst to become strict and the program to run out of heap.<br>
</div>
<div>By the way,&nbsp;Clean has it&#39;s share of rough edges.&nbsp; The reason I&#39;m hanging out on Haskell-Cafe is because I&#39;m trying to get away from those rough edges.&nbsp; But, I am&nbsp;missing Clean&#39;s uniqueness types.&nbsp;&nbsp;I&#39;m starting to see&nbsp;Haskell&#39;s unsafe functions as a blunt work around&nbsp;that could be fixed elegantly and safely by implementing uniqueness types.</div>

<div>&nbsp;</div>
<div>&nbsp;<br></div>