Send Beginners mailing list submissions to
        beginners@haskell.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        beginners-requ...@haskell.org

You can reach the person managing the list at
        beginners-ow...@haskell.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  Understanding recursion in Haskell.
      (the_polymo...@rocketmail.com)
   2.  Re: Understanding recursion in Haskell. (7stud)
   3. Re:  Understanding recursion in Haskell. (Sean Lee)
   4. Re:  Understanding recursion in Haskell. (Thomas Davie)
   5.  Re: Hudak state emulation discussion - can you   give me some
      idea? (Benjamin L.Russell)
   6.  How to display a time difference? (Colin Paul Adams)


----------------------------------------------------------------------

Message: 1
Date: Wed, 18 Mar 2009 00:36:57 -0700 (PDT)
From: the_polymo...@rocketmail.com
Subject: Re: [Haskell-beginners] Understanding recursion in Haskell.
To: beginners@haskell.org
Message-ID: <390551.23952...@web50807.mail.re2.yahoo.com>
Content-Type: text/plain; charset=iso-8859-1


Hi Adrian,

Thanks for the explanations. Could we perhaps examine one recursive example in 
detail, i.e., step-by-step, as I'm still confused? Maybe the following program 
from chapter 2 of 
http://book.realworldhaskell.org?

myDrop n xs = if n <= 0 || null xs
              then xs
              else myDrop (n - 1) (tail xs)


Danke,

Caitlin


--- On Wed, 3/18/09, Adrian Neumann <aneum...@inf.fu-berlin.de> wrote:

From: Adrian Neumann <aneum...@inf.fu-berlin.de>
Subject: Re: [Haskell-beginners] Understanding recursion in Haskell.
To: beginners@haskell.org
Date: Wednesday, March 18, 2009, 12:05 AM


Am 18.03.2009 um 06:28 schrieb Caitlin:

> 
> Hi.
> 
> As a Haskell
 beginner, I was wondering if someoneone could explain how the following 
programs function (pardon the pun)?
> 


This function takes some type which has an ordering defined, i.e. you can 
compare its elements to one another

> maximum' :: (Ord a) => [a] -> a

it doesn't work for an empty list

> maximum' [] = error "maximum of empty list"

the maximum of a one element list is the lone element. this is the base case 
which will be eventually reached by the recursion

> maximum' [x] = x

should the list have more than one element

> maximum' (x:xs)

compare the first element to the maximum of the other elements. if it's 
greater, it's the maximum

>     | x > maxTail = x

otherwise the maximum of the other elements is the maximum of the whole list

>     | otherwise = maxTail

how to compute the maximum of the other elements? just use
 this function again. after a while we will only have one element left and 
reach the base case above.

>     where maxTail = maximum' xs
> 
> 

This function takes a number and a list of some type a

> take' :: (Num i, Ord i) => i -> [a] -> [a]

first, ignore the list and check whether n is <= 0. in this case return an 
empty list. this is the base case, that's eventually reached by the recursion

> take' n _
>     | n <= 0   = []

otherwise, check if the list is empty. this is another base case.

> take' _ []     = []

if neither n<=0 or the list empty, take the first element, x, and put it on 
front of the prefix of length (n-1) of the other elements. use take' again, to 
get that prefix. after a while either n is 0 or there are no more elements in 
the list and we reach the  base case

> take' n (x:xs) = x : take' (n-1) xs
>
 
> 

Take two lists

> 
> zip' :: [a] -> [b] -> [(a,b)]

if either one of them is empty, stop

> zip' _ [] = []
> zip' [] _ = []

otherwise prepend a tuple, build from the two first elements to the zipped list 
of the other elements. after a while one of the lists should become empty and 
the base case is reached.

> zip' (x:xs) (y:ys) = (x,y):zip' xs ys
> 
> 
> 
> quicksort :: (Ord a) => [a] -> [a]

empty list -> nothing to do

> quicksort [] = []
> quicksort (x:xs) =

otherwise take the first element of the list and use it to split the list in 
two halves. one with all the elements that are smaller or equal than x, the 
other one with all those that are bigger. now sort them and put x in the 
middle. that should give us a sorted whole. how to sort them? just use 
quicksort again! after some splitting the lists will become empty
 and the recursion stops.

>     let smallerSorted = quicksort [a | a <- xs, a <= x]
>         biggerSorted = quicksort [a | a <- xs, a > x]
>     in  smallerSorted ++ [x] ++ biggerSorted


-----Inline Attachment Follows-----

_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners



      


------------------------------

Message: 2
Date: Wed, 18 Mar 2009 07:54:22 +0000 (UTC)
From: 7stud <bbxx789_0...@yahoo.com>
Subject: [Haskell-beginners] Re: Understanding recursion in Haskell.
To: beginners@haskell.org
Message-ID: <loom.20090318t073316-...@post.gmane.org>
Content-Type: text/plain; charset=us-ascii

Caitlin <The_Polymorph <at> rocketmail.com> writes:
> As a Haskell beginner, I was wondering if someoneone could explain how 
>the following programs function
> 
>maximum' :: (Ord a) => [a] -> a  
>maximum' [] = error "maximum of empty list"  
>maximum' [x] = x  
>maximum' (x:xs)   
>    | x > maxTail = x  
>    | otherwise = maxTail  
>    where maxTail = maximum' xs

I'm a beginner too.  Let's say you call:

maximum' [1, 2, 4]

First of all, a list like [1, 2, 4] is actually of the form 1:2:4:[].
So you are really calling:

maximum' 1:2:4:[]

That function call matches the pattern in this definition:

maximum' (x:xs)   
    | x > maxTail = x  
    | otherwise = maxTail  
    where maxTail = maximum' xs

Lining up the function call with the function definition:

maximum' (x:xs)
maximum'  1:2:4:[]

gives x = 1 and xs = 2:4:[].  Then the first condition("guard") in the 
function definition is examined:

| x > maxTail         = x

Because x = 1, the guard is equivalent to:

| 1 > maxTail         = 1

So is 1 greater than the value of maxTail?  What is the value of maxTail?  
maxTail is defined here:

maxTail = maximum' xs

Hmmm...that is starting to get confusing.  At this point, I draw a
diagram: 

maximum' 1:2:4:[]
 | 1 > maxTail  = 1
       [     ]--------> maximum' xs
 | otherwise maxTail

The blank([   ]) represents the value of maxTail. From above, you know 
that xs is 2:4:[], giving you:

maximum' 1:2:4:[]
 | 1 > maxTail  = 1
       [     ]--------> maximum' 2:4:[]
 | otherwise maxTail

Ok, so to figure out the value of maxTail, you have to figure out the value
of: 

maximum' 2:4:[].  

That function call matches the pattern in this definition:

maximum' (x:xs)   
    | x > maxTail = x  
    | otherwise = maxTail  
    where maxTail = maximum' xs

Lining up the function call with the function definition:

>maximum' (x:xs)
 maximum'  2:4:[]

gives x = 2 and xs = 4:[].  Then the first condition("guard") in 
the function definition is examined:

maximum' (x:xs)
    | x > maxTail = x
    | otherwise = maxTail
    where maxTail = maximum' xs

So is 2 greater than the value of maxTail?  What is the value of 
maxTail?  Uh oh, here we go again.  maxTail is defined here:

maxTail = maximum' xs

and this time xs = 4:[].  Time to update the diagram:

maximum' 1:2:4:[]
 | 1 > maxTail  = 1
       [     ]----------> maximum' 2:4:[]
 | otherwise maxTail       | 2 > maxTail   = 2                     
                                 [     ]---------> maximum' 4:[]
                           | otherwise maxTail

Now comes the fun part.  What is maximum' 4:[]? That function call 
matches one of the other definitions for maximum', this one:

maximum' [x] = x

That definition is the same as:

maximum' x:[] = x

Lining up the function call with the definition:

maximum' x:[] = x
maximum' 4:[]

Looking at the pattern in the function definition, you should be
able to see that x = 4, and therefore maximum' 4:[] = 4. 
Substituting 4 into right hand side of the current diagram:

maximum' 1:2:4:[]
 | 1 > maxTail  = 1
       [     ]----------> maximum' 2:4:[]
 | otherwise maxTail       | 2 > maxTail   = 2                     
                                 [     ]------------> 4
                           | otherwise maxTail


Ah ha!  Now we have a value for one of the blanks:  

maximum' 1:2:4:[]
 | 1 > maxTail  = 1
       [     ]----------> maximum' 2:4:[]
 | otherwise maxTail       | 2 > maxTail   = 2                     
                                 [  4  ]
                           | otherwise maxTail

Remember that a blank represents the value of maxTail above it.
Now you can answer the question: is 2 > 4?  That is false, so you 
look at the second guard condition:

| otherwise maxTail

That just returns the value of maxTail, which is 4.  That means the 
value of maximum' 2:4:[] is 4.  Updating the diagram:

maximum' 1:2:4:[]
 | 1 > maxTail  = 1
       [     ]----------> 4
 | otherwise maxTail                          
                            
Moving the 4 into the blank gives:
   
maximum' 1:2:4:[]
 | 1 > maxTail  = 1
       [  4  ]
 | otherwise maxTail         

That allows you to answer the question is 1 > 4.  That is false, so
you look at the second guard condition:

| otherwise maxTail

which just returns maxTail, or 4.  That means the value of 
maximum' 1:2:4:[] is 4. Ta da.

Try doing something similar with the other function definitions
to see if you can figure them out.



        












        













------------------------------

Message: 3
Date: Wed, 18 Mar 2009 19:13:30 +1100
From: Sean Lee <sean....@gmail.com>
Subject: Re: [Haskell-beginners] Understanding recursion in Haskell.
To: beginners@haskell.org
Message-ID:
        <856192540903180113r2fcddfebm1c8b370d6f056...@mail.gmail.com>
Content-Type: text/plain; charset=ISO-8859-1

This function drops the first n elements from xs.

> If n <= 0 || null xs
>   then xs

if n is less than or equal to 0, we are done dropping the elements
that we intended to drop.
If xs is null, the list is empty and we have no more elements to drop.
So, either way, we can just return xs and stop the recursion.

> else myDrop (n - 1) (tail xs)

Otherwise, we drop the first element from xs and pass that to myDrop.
Of course, when we call myDrop, we give n-1 instead of n because we
dropped the first element from xs.


I think it will be easier if we take an example.

Let's say we want to evaluate myDrop 3 [1,2,3,4,5], expecting the
output to be [4,5].

3 is greater than 0 and [1,2,3,4,5] is not empty.
So, it evaluates to

myDrop (3 - 1) (tail [1,2,3,4,5])

2 is greater than 0 and [2,3,4,5] is not empty
So, it evaluates to

myDrop (2 - 1) (tail [2,3,4,5])

1 is greater than 0 and [3,4,5] is not empty
So, it evaluates to

myDrop (1 -1) (tail [3,4,5])

0 is now equal to 0,
so it evaluates to

[4,5].


Sean

On Wed, Mar 18, 2009 at 6:36 PM,  <the_polymo...@rocketmail.com> wrote:
>
> Hi Adrian,
>
> Thanks for the explanations. Could we perhaps examine one recursive example 
> in detail, i.e., step-by-step, as I'm still confused? Maybe the following 
> program from chapter 2 of
> http://book.realworldhaskell.org?
>
> myDrop n xs = if n <= 0 || null xs
>               then xs
>               else myDrop (n - 1) (tail xs)
>
>
> Danke,
>
> Caitlin
>
>
> --- On Wed, 3/18/09, Adrian Neumann <aneum...@inf.fu-berlin.de> wrote:
>
> From: Adrian Neumann <aneum...@inf.fu-berlin.de>
> Subject: Re: [Haskell-beginners] Understanding recursion in Haskell.
> To: beginners@haskell.org
> Date: Wednesday, March 18, 2009, 12:05 AM
>
>
> Am 18.03.2009 um 06:28 schrieb Caitlin:
>
>>
>> Hi.
>>
>> As a Haskell
>  beginner, I was wondering if someoneone could explain how the following 
> programs function (pardon the pun)?
>>
>
>
> This function takes some type which has an ordering defined, i.e. you can 
> compare its elements to one another
>
>> maximum' :: (Ord a) => [a] -> a
>
> it doesn't work for an empty list
>
>> maximum' [] = error "maximum of empty list"
>
> the maximum of a one element list is the lone element. this is the base case 
> which will be eventually reached by the recursion
>
>> maximum' [x] = x
>
> should the list have more than one element
>
>> maximum' (x:xs)
>
> compare the first element to the maximum of the other elements. if it's 
> greater, it's the maximum
>
>>     | x > maxTail = x
>
> otherwise the maximum of the other elements is the maximum of the whole list
>
>>     | otherwise = maxTail
>
> how to compute the maximum of the other elements? just use
>  this function again. after a while we will only have one element left and 
> reach the base case above.
>
>>     where maxTail = maximum' xs
>>
>>
>
> This function takes a number and a list of some type a
>
>> take' :: (Num i, Ord i) => i -> [a] -> [a]
>
> first, ignore the list and check whether n is <= 0. in this case return an 
> empty list. this is the base case, that's eventually reached by the recursion
>
>> take' n _
>>     | n <= 0   = []
>
> otherwise, check if the list is empty. this is another base case.
>
>> take' _ []     = []
>
> if neither n<=0 or the list empty, take the first element, x, and put it on 
> front of the prefix of length (n-1) of the other elements. use take' again, 
> to get that prefix. after a while either n is 0 or there are no more elements 
> in the list and we reach the  base case
>
>> take' n (x:xs) = x : take' (n-1) xs
>>
>
>>
>
> Take two lists
>
>>
>> zip' :: [a] -> [b] -> [(a,b)]
>
> if either one of them is empty, stop
>
>> zip' _ [] = []
>> zip' [] _ = []
>
> otherwise prepend a tuple, build from the two first elements to the zipped 
> list of the other elements. after a while one of the lists should become 
> empty and the base case is reached.
>
>> zip' (x:xs) (y:ys) = (x,y):zip' xs ys
>>
>>
>>
>> quicksort :: (Ord a) => [a] -> [a]
>
> empty list -> nothing to do
>
>> quicksort [] = []
>> quicksort (x:xs) =
>
> otherwise take the first element of the list and use it to split the list in 
> two halves. one with all the elements that are smaller or equal than x, the 
> other one with all those that are bigger. now sort them and put x in the 
> middle. that should give us a sorted whole. how to sort them? just use 
> quicksort again! after some splitting the lists will become empty
>  and the recursion stops.
>
>>     let smallerSorted = quicksort [a | a <- xs, a <= x]
>>         biggerSorted = quicksort [a | a <- xs, a > x]
>>     in  smallerSorted ++ [x] ++ biggerSorted
>
>
> -----Inline Attachment Follows-----
>
> _______________________________________________
> Beginners mailing list
> Beginners@haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
>
>
>
> _______________________________________________
> Beginners mailing list
> Beginners@haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>



-- 
Sean Lee
PhD Student
Programming Language and Systems Research Group
School of Computer Science and Engineering
University of New South Wales


------------------------------

Message: 4
Date: Wed, 18 Mar 2009 09:28:52 +0100
From: Thomas Davie <tom.da...@gmail.com>
Subject: Re: [Haskell-beginners] Understanding recursion in Haskell.
To: the_polymo...@rocketmail.com
Cc: beginners@haskell.org
Message-ID: <d1d5096a-4eda-4a9f-b81c-8f4ef147c...@gmail.com>
Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes


On 18 Mar 2009, at 08:36, the_polymo...@rocketmail.com wrote:

>
> Hi Adrian,
>
> Thanks for the explanations. Could we perhaps examine one recursive  
> example in detail, i.e., step-by-step, as I'm still confused? Maybe  
> the following program from chapter 2 of
> http://book.realworldhaskell.org?
>
> myDrop n xs = if n <= 0 || null xs
>               then xs
>               else myDrop (n - 1) (tail xs)

In this example, I'm gonna use the "~>" symbol to mean "reduces to",  
that is, if you perform one more evaluation step, you get this.  We're  
going to try and evaluate myDrop 2 [1,2,3,4]

    myDrop 2 [1,2,3,4]
    { Reduce myDrop 2 [1,2,3,4] to its right hand side as defined  
above }
~> if 2 <= 0 || null [1,2,3,4] then [1,2,3,4] else myDrop (2-1) (tail  
[1,2,3,4])
    { Reduce 2 <= 0 to False }
~> if False || null [1,2,3,4] then [1,2,3,4] else myDrop (2-1) (tail  
[1,2,3,4])
    { Reduce null [1,2,3,4] to False
~> if False || False then [1,2,3,4] else myDrop (2-1) (tail [1,2,3,4])
     { Reduce False || False to False }
~> if False then [1,2,3,4] else myDrop (2-1) (tail [1,2,3,4])
    { Reduce the if expression to its else branch }}
~> myDrop (2-1) (tail [1,2,3,4])
    {Reduce myDrop (2-1) (tail [1,2,3,4]) to its right hand side as  
defined above }
~> if n <= 0 || null xs then xs else myDrop (n - 1) (tail xs) where n  
= (2-1); xs = tail [1,2,3,4]
    { Reduce 2 - 1 to 1 }
~> if n <= 0 || null xs then xs else myDrop (n - 1) (tail xs) where n  
= 1; xs = tail [1,2,3,4]
    { Reduce 1 <= 0 to False }
~> if False || null xs then xs else myDrop (n - 1) (tail xs) where n =  
1; xs = tail [1,2,3,4]
    { Remove superfluous definition of n (there's only one use of it  
now) }
~> if False || null xs then xs else myDrop (1 - 1) (tail xs) where xs  
= tail [1,2,3,4]
    { Reduce tail [1,2,3,4] to [2,3,4] }
~> if False || null xs then xs else myDrop (1 - 1) (tail xs) where xs  
= [2,3,4]
    { Reduce null [2,3,4] to False }
~> if False || False then xs else myDrop (1 - 1) (tail xs) where xs =  
[2,3,4]
    { Reduce False || False to False }
~> if False then xs else myDrop (1 - 1) (tail xs) where xs = [2,3,4]
    { Reduce if expression to its else branch }
~> myDrop (1 - 1) (tail xs) where xs = [2,3,4]
    { Remove superfluous definition of xs as there's only one use of  
it now }
~> myDrop (1 - 1) (tail [2,3,4])
    { Reduce myDrop (1 - 1) (tail [2,3,4]) to its right hand side as  
defined above }
~> if n <= 0 || null xs then xs else myDrop (n - 1) (tail xs) where n  
= (1 - 1); xs = tail [2,3,4]
    { Reduce 1 - 1 to 0 }
~> if n <= 0 || null xs then xs else myDrop (n - 1) (tail xs) where n  
= 0; xs = tail [2,3,4]
    { Reduce 0 <= 0 to True }
~> if True || null xs then xs else myDrop (n - 1) (tail xs) where n =  
0; xs = tail [2,3,4]
    { Remove superfluous definition of n, as its only used in one  
place now }
~> if True || null xs then xs else myDrop (0 - 1) (tail xs) where xs =  
tail [2,3,4]
    { Reduce True || anything to True }
~> if True then xs else myDrop (0 - 1) (tail xs) where xs = tail [2,3,4]
    { Reduce if expression to its then branch }
~> xs where xs = tail [2,3,4]
    { Remove superfluous definition of xs, as it only appears once }
~> tail [2,3,4]
    { Reduce tail [2,3,4] to [3,4] }
~> [3,4]

Hope that helps

Bob


------------------------------

Message: 5
Date: Wed, 18 Mar 2009 18:59:40 +0900
From: Benjamin L.Russell <dekudekup...@yahoo.com>
Subject: [Haskell-beginners] Re: Hudak state emulation discussion -
        can you give me some idea?
To: beginners@haskell.org
Message-ID: <m6h1s459radd4h3tfggnbg5o1r76cmn...@4ax.com>
Content-Type: text/plain; charset=us-ascii

On Wed, 18 Mar 2009 13:02:34 +0530, Girish Bhat
<girishbhat6...@gmail.com> wrote:

>>[...]
>>
>> Hope this helps....
>>
>Thanks! It does. I think what threw me was that while there is enough
>redundancy in what he states for someone more clever than me, he would
>have explicitly stated before hand  that he was defining the operators
>[:=], [+'], ['if] etc.:)

But he did; specifically, on pages 405 (the previous page) to 406 of
the volume, Hudak writes as follows:

>For expository purposes we would like to 
>make the state as implicit as possible, and 
>thus we express the result as a composition 
>of higher-order functions. To facilitate this 
>and to make the result look as much like 
>the original program as possible, we define 
>the following higher-order infix operators 
>and functions(22): 

So he did in fact explicitly state beforehand that he was defining
those operators.

-- Benjamin L. Russell
-- 
Benjamin L. Russell  /   DekuDekuplex at Yahoo dot com
http://dekudekuplex.wordpress.com/
Translator/Interpreter / Mobile:  +011 81 80-3603-6725
"Furuike ya, kawazu tobikomu mizu no oto." 
-- Matsuo Basho^ 



------------------------------

Message: 6
Date: Wed, 18 Mar 2009 10:06:30 +0000
From: Colin Paul Adams <co...@colina.demon.co.uk>
Subject: [Haskell-beginners] How to display a time difference?
To: beginners@haskell.org
Message-ID: <m37i2ntaah....@colina.demon.co.uk>
Content-Type: text/plain; charset=us-ascii

The code of the following routine is intended to indicate how long it
takes for the computer to make a move. However the time is printed (as
very close to zero) long before the move is made.

I must be missing something about sequencing actions in the IO monad.

play_move :: IORef Game_state -> IO ()
play_move game_state_ior = do
  (_, state, _) <- readIORef game_state_ior  
  putStr "Playing AI: "
  start_time <- getCurrentTime
  let move = recommended_move state
  modifyIORef game_state_ior (update_interactive_from_move move)
  end_time <- getCurrentTime
  putStrLn $ show $ (diffUTCTime end_time start_time)

-- 
Colin Adams
Preston Lancashire


------------------------------

_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 9, Issue 19
****************************************

Reply via email to