Re: [Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-12 Thread Bernie Pope

Lennart Augustsson wrote:

Sure, but we also have

para f e xs = snd $ foldr (\ x ~(xs, y) -> (x:xs, f x xs y)) ([], e) xs

Nice one.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-12 Thread Lennart Augustsson

Sure, but we also have

para f e xs = snd $ foldr (\ x ~(xs, y) -> (x:xs, f x xs y)) ([], e) xs

So I think using para is fine.

-- Lennart

On Feb 12, 2007, at 18:40 , Bernie Pope wrote:


Nicolas Frisby wrote:

Guess this is a tricky choice for a foldr intro, since it requires a
"paramorphism" (see bananas lenses wires etc.)

para :: (a -> [a] -> b -> b) -> b -> [a] -> b
para f e [] = e
para f e (x:xs) = f x xs (para f e xs)

-- note that the original tail of the list (i.e. xs and not xs') is
used in the else-branch
dropWhile' p = para (\x xs xs' -> if p x then xs' else (x:xs)) []
Actually, several people tried to use para, but of course it is not  
in the spirit of the challenge :)


Cheers,
Bernie.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-12 Thread Nicolas Frisby

Oops; I totally forgot the context of this whole discussion!

I enjoyed your article.

On 2/12/07, Bernie Pope <[EMAIL PROTECTED]> wrote:

Nicolas Frisby wrote:
> Guess this is a tricky choice for a foldr intro, since it requires a
> "paramorphism" (see bananas lenses wires etc.)
>
> para :: (a -> [a] -> b -> b) -> b -> [a] -> b
> para f e [] = e
> para f e (x:xs) = f x xs (para f e xs)
>
> -- note that the original tail of the list (i.e. xs and not xs') is
> used in the else-branch
> dropWhile' p = para (\x xs xs' -> if p x then xs' else (x:xs)) []
Actually, several people tried to use para, but of course it is not in
the spirit of the challenge :)

Cheers,
Bernie.


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-12 Thread Bernie Pope

Nicolas Frisby wrote:

Guess this is a tricky choice for a foldr intro, since it requires a
"paramorphism" (see bananas lenses wires etc.)

para :: (a -> [a] -> b -> b) -> b -> [a] -> b
para f e [] = e
para f e (x:xs) = f x xs (para f e xs)

-- note that the original tail of the list (i.e. xs and not xs') is
used in the else-branch
dropWhile' p = para (\x xs xs' -> if p x then xs' else (x:xs)) []
Actually, several people tried to use para, but of course it is not in 
the spirit of the challenge :)


Cheers,
Bernie.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-12 Thread Nicolas Frisby

Guess this is a tricky choice for a foldr intro, since it requires a
"paramorphism" (see bananas lenses wires etc.)

para :: (a -> [a] -> b -> b) -> b -> [a] -> b
para f e [] = e
para f e (x:xs) = f x xs (para f e xs)

-- note that the original tail of the list (i.e. xs and not xs') is
used in the else-branch
dropWhile' p = para (\x xs xs' -> if p x then xs' else (x:xs)) []

Prelude> dropWhile' (<5) [1,2,3,4,5,6,7,8]
[5,6,7,8]
Prelude> dropWhile' (<5) [1,2,3,4,5,6,7,1]
[5,6,7,1]
Prelude> :m + Test.QuickCheck
Prelude Test.QuickCheck> :m + Text.Show.Functions
Prelude Test.QuickCheck Text.Show.Functions>
   quickCheck $ \p l -> dropWhile p (l :: [Int]) == dropWhile' p l
Loading package QuickCheck-1.0 ... linking ... done.
OK, passed 100 tests.


On 2/12/07, Donald Bruce Stewart <[EMAIL PROTECTED]> wrote:

pixel:
> Chris Moline <[EMAIL PROTECTED]> writes:
>
> > dropWhile p = foldr (\x l' -> if p x then l' else x:l') []
>
> invalid:  dropWhile (< 5) [1, 10, 1]  should return [10, 1]

Prelude Test.QuickCheck Text.Show.Functions> quickCheck $ \p xs -> dropWhile p xs 
== foldr (\x l' -> if p x then l' else x:l') [] (xs :: [Int])

Falsifiable, after 4 tests:

[-1,-3,1]


If in doubt, do a quick check!

-- Don
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-12 Thread Donald Bruce Stewart
pixel:
> Chris Moline <[EMAIL PROTECTED]> writes:
> 
> > dropWhile p = foldr (\x l' -> if p x then l' else x:l') []
> 
> invalid:  dropWhile (< 5) [1, 10, 1]  should return [10, 1]

Prelude Test.QuickCheck Text.Show.Functions> quickCheck $ \p xs -> dropWhile p 
xs == foldr (\x l' -> if p x then l' else x:l') [] (xs :: [Int])

Falsifiable, after 4 tests:

[-1,-3,1]


If in doubt, do a quick check!

-- Don
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-12 Thread Pixel
Chris Moline <[EMAIL PROTECTED]> writes:

> dropWhile p = foldr (\x l' -> if p x then l' else x:l') []

invalid:  dropWhile (< 5) [1, 10, 1]  should return [10, 1]
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold

2007-02-11 Thread Chris Moline
I hope the following doesn't come across as
condescending...

The recent issue of The Monad Reader has generated
some excitement, mostly to do with the time travel
article. I, however, would like to discuss a simpler
solution to implementing dropWhile with foldr, which
is discussed in the first article of TMR.

When I was taught about folds, I was told that foldr
starts at the end of the list and then builds up the
result from there. But this turns out to be an
unhelpful way of thinking. It's better to say foldr
starts at the beginning of the list, just like foldl.
But how does this work? To see, we'll start by
implementing a simpler function than dropWhile, one
which determines whether we should cons an element
onto a list or just return the list.

dropHead p x xs = if p x then xs else x:xs

Note that I've funnily given a separate arg to the
head of the list and to its tail. That's not a typo
and later we will see why.

Now let's apply dropHead to each element of the list
[1, 2, 3, 4, 5]:

map (dropHead p) [1, 2, 3, 4 ,5] =>
[dropHead p 1,
 dropHead p 2,
 dropHead p 3,
 dropHead p 4,
 dropHead p 5]

Now we need to figure out where to get the second
argument for each of the dropHead applications. I
know! If a call to dropHead comes before another call
to dropHead, we'll pass the result of the second call
as the second arg of the first. And if there are no
calls after a call to dropHead, we'll pass our base
case as the second arg to that call. Let's have a
look:

threadResults basec [] = basec
threadResults basec [f:fs] = f $ threadResults basec
fs

threadResults [] [dropHead p 1 ...] =
 dropHead p 1 $
 dropHead p 2 $
 dropHead p 3 $
 dropHead p 4 $
 dropHead p 5 []

Let's see it in action! First let's let our predicate
determine whether a value is less than three.

dropHead (< 3) 5 [] =
 if (< 3) 5 then [] else 5:[] => [5]
dropHead (< 3) 4 [5] =
 if (< 3) 4 then [5] else 4:[5] => [4, 5]
dropHead (< 3) 3 [4, 5] =
 if (< 3) 3 then [4, 5] else 3:[4, 5] => [3, 4, 5]
dropHead (< 3) 2 [3, 4, 5] =
 if (< 3) 2 then [3, 4, 5] else 2:[3, 4, 5] => [3, 4,
5]
dropHead (< 3) 1 [3, 4, 5] =
 if (< 3) 1 then [3, 4, 5] else 1:[3, 4, 5] => [3, 4,
5]
=> [3, 4, 5]

Do you now see how foldr works? It starts at the
beginning of the list and applies the function you
gave it to the first element of the list. Then to get
the second argument of the first call, it applies your
function to the second element of the list and passes
the result of that to the first call. In other words,
it /recurs/ on the next element of the list. When we
finally get to the end, the base case is passed to the
final call of your function and it returns, and all
the previous calls return building their results from
the calls after.

So in other words to implement dropWhile with foldr
merely requires:

dropHead p x xs = if p x then xs else x:xs
dropWhile p l = foldr (dropHead p) [] l

Or even simpler:

dropWhile p = foldr (\x l' -> if p x then l' else
x:l') []

take 3 $ dropWhile (< 5) [1..]
=> [5, 6, 7]

No abtruse machinery required!

__
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe