There&#39;s at least one thing; I won&#39;t call it a flaw in your logic, but it&#39;s not true of my usage. Your definition always produces a non-null list. The particular g in my mind will eventually produce a null list, somewhere down the line. I think if that&#39;s true, we can guarantee termination. <br>
<br><div class="gmail_quote">On Sat, Jan 24, 2009 at 10:16 PM, Ryan Ingram <span dir="ltr">&lt;<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>&gt;</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;">
foldr f z xs =<br>
 &nbsp; x0 `f` (x1 `f` (x2 `f` ... (xN `f` z) ...))<br>
<br>
In particular, note that if f is a total function, xs is finite and<br>
totally defined, and z is totally defined, then the result of this<br>
fold is totally defined.<br>
<br>
Now consider your &quot;f&quot; (rewritten slightly)<br>
<br>
f x xs<br>
 &nbsp; | null xs = []<br>
 &nbsp; | p x = []<br>
 &nbsp; | otherwise = foldr f (x:xs) (g x xs)<br>
<br>
with these definitions:<br>
<br>
c _ = False<br>
g = (:)<br>
<br>
c and g are definitely total functions, so what happens when we<br>
evaluate f 0 [1]?<br>
<br>
f 0 [1]<br>
 &nbsp; &nbsp; &nbsp; &nbsp;= foldr f [0,1] [0,1]<br>
 &nbsp; &nbsp; &nbsp; &nbsp;= let t1 = foldr f [0,1] [1] in f 0 $ t1<br>
 &nbsp; &nbsp; &nbsp; &nbsp;= let t1 = foldr f [0,1] [1] in foldr f (0 : t1) (0 : t1)<br>
 &nbsp; &nbsp; &nbsp; &nbsp;= let t1 = foldr f [0,1] [1]<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;t2 = foldr f (0:t1) t1<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;in f 0 t2<br>
<br>
etc.; this is clearly non-terminating.<br>
<br>
Therefore there is no way to make f into a fold.<br>
<br>
Any errors in my logic?<br>
<br>
 &nbsp;-- ryan<br>
<br>
2009/1/24 Andrew Wagner &lt;<a href="mailto:wagner.andrew@gmail.com">wagner.andrew@gmail.com</a>&gt;:<br>
<div><div></div><div class="Wj3C7c">&gt; Ahem. That&#39;s what happens when you don&#39;t type-check your brainstorming<br>
&gt; before barfing it out, kids. Sorry about that. Let&#39;s try this again:<br>
&gt;<br>
&gt; f _ [] = []<br>
&gt; f y x | c y = []<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; | otherwise = foldr f (y:x) (g y x)<br>
&gt;<br>
&gt; I&#39;ve got a fold on the inside now, but I&#39;m pretty sure the whole thing is<br>
&gt; just a fold. Not quite there yet, though...<br>
&gt;<br>
&gt; On Sat, Jan 24, 2009 at 1:42 PM, Andrew Wagner &lt;<a href="mailto:wagner.andrew@gmail.com">wagner.andrew@gmail.com</a>&gt;<br>
&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Actually, I think I can rewrite it this way:<br>
&gt;&gt;<br>
&gt;&gt; f xs [] = False<br>
&gt;&gt; f xs (y:ys) | any c ys&#39; = True<br>
&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | otherwise = f (f (y:xs) ys&#39;) ys<br>
&gt;&gt; &nbsp; where ys&#39; = g y ys<br>
&gt;&gt;<br>
&gt;&gt; This should help, I think.<br>
&gt;&gt;<br>
&gt;&gt; On Sat, Jan 24, 2009 at 12:11 PM, Dan Doel &lt;<a href="mailto:dan.doel@gmail.com">dan.doel@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On Saturday 24 January 2009 11:39:13 am Andrew Wagner wrote:<br>
&gt;&gt;&gt; &gt; This is almost a fold, but seemingly not quite? I know I&#39;ve seem some<br>
&gt;&gt;&gt; &gt; talk<br>
&gt;&gt;&gt; &gt; of folds that potentially &quot;quit&quot; early. but not sure where I saw that,<br>
&gt;&gt;&gt; &gt; or<br>
&gt;&gt;&gt; &gt; if it fits.<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; f xs [] = False<br>
&gt;&gt;&gt; &gt; f xs (y:ys) | any c ys&#39; = True<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | otherwise = f (nub (y:xs)) (ys&#39; ++ ys)<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; &nbsp; &nbsp;where ys&#39; = g y xs<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Quitting early isn&#39;t the problem. For instance, any is defined in terms<br>
&gt;&gt;&gt; of<br>
&gt;&gt;&gt; foldr, and it works fine on infinite lists, quitting as soon as it finds<br>
&gt;&gt;&gt; a<br>
&gt;&gt;&gt; True. As long as you don&#39;t use the result of the recursive call (which is<br>
&gt;&gt;&gt; the<br>
&gt;&gt;&gt; second argument in the function you pass to foldr), it will exit early.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The problem is that your function doesn&#39;t look structurally recursive,<br>
&gt;&gt;&gt; and<br>
&gt;&gt;&gt; that&#39;s what folds (the usual ones, anyway) are: a combinator for<br>
&gt;&gt;&gt; structural<br>
&gt;&gt;&gt; recursion. The problem is in your inductive case, where you don&#39;t just<br>
&gt;&gt;&gt; recurse<br>
&gt;&gt;&gt; on &quot;ys&quot;, you instead recurse on &quot;ys&#39; ++ ys&quot;, where ys&#39; is the result of<br>
&gt;&gt;&gt; an<br>
&gt;&gt;&gt; arbitrary function. folds simply don&#39;t work that way, and only give you<br>
&gt;&gt;&gt; access<br>
&gt;&gt;&gt; to the recursive call over the tail, but in a language like Agda, the<br>
&gt;&gt;&gt; termination checker would flag even this definition, and you&#39;d have to,<br>
&gt;&gt;&gt; for<br>
&gt;&gt;&gt; instance, write a proof that this actually does terminate, and do<br>
&gt;&gt;&gt; induction on<br>
&gt;&gt;&gt; the structure of the proof, or use some other such technique for writing<br>
&gt;&gt;&gt; non-<br>
&gt;&gt;&gt; structurally recursive functions.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -- Dan<br>
&gt;&gt;<br>
&gt;<br>
&gt;<br>
</div></div>&gt; _______________________________________________<br>
&gt; Haskell-Cafe mailing list<br>
&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
&gt;<br>
&gt;<br>
</blockquote></div><br>