let (d,k) = (g x y, h x d) ..

Derek Elkins ddarius@hotpop.com
Fri, 27 Jun 2003 04:52:31 -0400


On Fri, 27 Jun 2003 12:22:46 +0400
"Serge D. Mechveliani" <mechvel@botik.ru> wrote:

> Dear Haskellers,
> 
> Once I wrote a function 
> 
>   f' :: Int -> Int -> Int -> (Int, Int)
> 
>   f' n m l = let (d,k) = (gcd n m, quot n d)  in  (k, l*k)
> 
> (the simplified version of real program),
> placing erroneousely  d  to both parts of the pattern matching 
> (d,k) = ...
> 
> The intended program was
> 
>   f  n m l = let {d = gcd n m;  k = quot n d} in  (k, l*k)
> 
> But f' gives the intended results, at least in the GHC 
> implementation. 
> So that I did not notice the `error' for a long time.
> 
> Is really the Haskell pattern matching semantic so that f and f' 
> are equivalent ?

Haskell is a lazy language.  You can define values in terms of
themselves (with emphasis on -values-).

Here's a (relatively) simple example of doing this for more and (some)
explanation see http://haskell.org/hawiki/TyingTheKnot.

-- list_rep_min: replace list with it's minimum value in one pass
list_rep_min l = result
    where (result,mini) = lrm l mini
          lrm [x] m = ([m],x)
          lrm (x:xs) m = (m:ms,x `min` m')
		where (ms,m') = lrm xs m

> Is it an occasional implementation feature that hide the `error'?

No.  It's a language feature, though it does cause problems.  My advice
is simply to avoid shadowing (local) variables.  I am usually pretty
good about following it, but one particular time I didn't, I ended up
with a function that seemed 'mysteriously' broken.  I felt pretty stupid
when I finally noticed what it was.  Oddly, enough I was actually
thinking that I was shadowing too much as I wrote the code.