Posted By: Charles | Nov 5th @ 7:53 AM | 32,493 Views | 24 Comments
We've kicked off C9 Lectures with a journey into the world of Functional Programming with functional language purist and high priest of the lambda calculus, Dr. Erik Meijer (you can thank Erik for many of the functional constructs that have shown up in languages like C# and VB.NET. When you use LINQ, thank Erik in addition to Anders). 

We will release a new chapter in this series every Thursday.

In Chapter 6, Dr. Meijer guides us through the world of recursive functions. In Haskell, functions can be defined in terms of themselves.  Such functions are called recursive.
For example: 

factorial 0 = 1
factorial (n+1) = (n+1) * factorial n

factorial maps 0 to 1, and any other positive integer to the product of itself and the factorial of its predecessor.

Some functions, such as factorial, are simpler to define in terms of other functions. As we shall see, however, many functions can naturally be defined in terms of themselves.

Properties of functions defined using recursion can be proved using the simple but powerful mathematical technique of induction.


You should watch these in sequence (or skip around depending on your curent level of knowledge in this domain):

Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5

Now, we do have a textbook and you should go buy it: The great Graham Hutton's Programming in Haskell. We worked with the publisher, Cambridge University Press, to get all Niners a 20% discount on the book. Now, you don't need the book to learn a great deal from this lecture series since Graham's website has all the slides and samples from the book as well as answers to the exercises. That said, it's highly recommended reading and you should consider it.

The promotion code is 09HASK and it is vaild on both the Hardback:

9780521871723 and Paperback: 9780521692694. The catalog pages are:

Hardback:

http://www.cambridge.org/us/catalogue/catalogue.asp?isbn=9780521871723 and the paperback is:

http://www.cambridge.org/us/catalogue/catalogue.asp?isbn=9780521692694

Note: This special offer is valid until December 31, 2009

Rating:
13
0
exoteric
exoteric
I : Next<I>

OK, this is a quick write-up that would seem to fit the bill

 

public static class Extensions
{
    public static IEnumerable<Tuple<A, B>> Zip<A, B>(this IEnumerable<A> ps, IEnumerable<B> qs)
    {
        if (ps == null)
            throw new ArgumentNullException("ps");
        if (qs == null)
            throw new ArgumentNullException("qs");
        return ps.DoZip(qs);
    }
    private static IEnumerable<Tuple<A, B>> DoZip<A, B>(this IEnumerable<A> ps, IEnumerable<B> qs)
    {
        using (var pe = ps.GetEnumerator())
        {
            using (var qe = qs.GetEnumerator())
            {
                while (pe.MoveNext() && qe.MoveNext())
                    yield return new Tuple<A, B>(pe.Current, qe.Current);
            }
        }
    }
}

  • Using nested using statements for resource disposal, as prescibed by C# for easy exception safe resource disposal.
  • Using a separate method to ensure exceptions are thrown upon calling the method.
This doesn't use the more generic version using a function but the pattern is the same (the lower-order Zip can of course be written in terms of the higher-order Zip using Tuple.Create).
As for writing Zip in terms of other LINQ operators: haven't looked into it but you wrote about that, I remember, although not what your precise solution was.

I think it's amusing that you refer to Hughes paper on FP as such a good paper, because I'm taking a class of his right now, and he strongly recommends this video series Smiley And, yes, it's a great paper. Good read. Thanks for the awesome video lectures, they complement his course very well!

Here is my take on the homework:

 

1.- Define:

 

and :

and' :: [Bool] -> Bool
and' [] = True
and' (False:_)  = False
and' (_:xs)     = and xs

 

concat:

concat' :: [[a]] -> [a]
concat' [] = []
concat' (xs:xss) = xs ++ concat' xss

 

replicate:

replicate' :: Int -> a -> [a]
replicate' 0 x = []
replicate' (n+1) x = x:replicate' n x

 

Select the Nth statement of a list:

(!!@) :: [a] -> Int -> a
(!!@) (x:_) 0 = x
(!!@) (_:xs) (n+1) = xs !!@ n

 

elem:

elem' :: (Eq a) => a -> [a] -> Bool
elem' _ [] = False
elem' x (y:ys) | x == y = True
               | otherwise = elem' x ys

 

2. Define merge :: [Int] -> [Int] -> [Int]

merge:: (Ord a) => [a] -> [a] -> [a]
merge [] [] = []
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) | x < y = x:merge xs (y:ys)
                    | x == y = x:y:merge xs ys
                    | otherwise = y:merge (x:xs) ys

 

3. Define merge sort:

msort :: (Ord a) => [a] -> [a]
msort [] = []
msort [x] = [x]
msort xs = merge (msort ys) (msort zs)
           where [(ys,zs)] = halve xs

halve :: [a] -> [([a],[a])]
halve [] = []
halve xs = [(take n xs, drop n xs)]
           where n = (length xs `div` 2)

 

I'm having a blast with this series. Smiley

exoteric
exoteric
I : Next<I>

It's probably not a complete coincidence that Charles speaks of the high priests of the Lambda calculus.

 

- folded hands, closed eyes, tilted head, pointing to the sky

 

May the monad be with you!

 

Big Smile

Somewhere closer to the end of the talk, Mr. Meijer says that segregation of common parts

of a function from the distinct parts is only possible with lazy evaluation (with the two clouds

drawn on the board). Didn't he really mean functional composition instead, which is more

general than lazy evaluation? If the distinct parts have no side-effects and the common part has

no influence on the distinct parts besides parametrization (as is the case with pure functions),

then you can also call the common part as a function with distinct parts as pure functional or

value parameters to that common function.

 

Of course you might save some computations with lazy evaluation, but I am quite sure I have

applied this technique with eager evaluation as well!

 

Am I missing something?

Microsoft Communities