Last in the (unplanned!) series on decorate-sort-undecorate in Haskell, this post reports on the Further Work necessary after the reponses to my initial query on haskell-beginners.

I received many helpful responses, many of which used Haskell language features which were new to me. Here I summarise them and then give a description of the new elements.

  1. Responses
    1. Quoted
    2. Standardised
  2. Discussion
    1. $
    2. (\x -> (f x))
    3. .
    4. &&& and id

  3. And the winner is, …

Read the rest of this entry »

This is not really a post, more like a braindump. I need somewhere to offload all this so I can go to bed. I apologise for lack of context.

OK some context: I’m looking for a chat application I can use within a django-based website (and if I can’t find one, girding my loins to write one). Irrelevantly (or so I’d thought until a few minutes ago) I’m learning Haskell, and finding out about functional programming.

Haskell:

Erlang:

Haskell: sort and sortBy

Friday, 3rd July, 2009

A comment in the discussion on decorate-sort-undecorate in Haskell pointed out to me that my naive and dsu versions of sort by length had different type signatures: the dsu version needlessly required elements of the list to be of type Ord:

sortByLength :: [[a]] -> [[a]]
sortByLength xs = sortBy (comparing length) xs

dsuSortByLength1 :: (Ord a) => [[a]] -> [[a]] 
dsuSortByLength1 xs = map snd (sort (zip (map length xs) xs))

My intention had been that the dsu version have the same requirements as the naive version. So where did this (Ord a) context come from, and how do we get rid of it?

The relevant difference between the functions is the different type signatures for sort and sortBy:

> :type sort
sort :: (Ord a) => [a] -> [a]
> :type sortBy
sortBy :: (a -> a -> Ordering) -> [a] -> [a]

sort requires list elements to be comparable (obviously); sortBy requires only a function that can generate an ordering from its input pair. In dsuSortByLength1 above, the elements of (zip (map length a) a) are required to be of type Ord. We could protest that just because (zip (map length a) a) has to be Ord doesn’t mean that a has to be Ord, but I suspect the compiler is playing on the safe side. [update: see first two comments.]

A function using sortBy instead of sort avoids this extra requirement in the type signature, and shows us a use case for comparing:

sortByLength :: [[a]] -> [[a]]
sortByLength xs = sortBy (comparing length) xs

dsuSortByLength2 :: [[a]] -> [[a]] 
dsuSortByLength2 xs = map snd (sortBy (comparing fst) (zip (map length xs) xs))

Using sortBy (comparing fst) rather than sort allows us to simplfy the type signature.

We can extract length to generalise the function:

sortByFunc :: (Ord a) => (a1 -> a) -> [a1] -> [a1]
sortByFunc f xs = sortBy (comparing f) xs

dsuByFunc  :: (Ord a) => (a1 -> a) -> [a1] -> [a1]
dsuByFunc  f xs = map snd (sortBy (comparing fst) (zip (map f xs) xs))

The (Ord a) context has returned! But here it is just a requirement on the output of the comparison function, which is fine.

Haskell resources page

Tuesday, 30th June, 2009

I’ve created a new Haskell resources page (see right) to help me keep track of the online resources I use while working through Real World Haskell.

Here are three version of sortByLength:

import Data.List

-- [1]

longer :: [a] -> [a] -> Ordering 
longer a b = compare (length a) (length b)

sortByLength0 :: [[a]] -> [[a]]
sortByLength0 a = sortBy longer a

-- [2]

import Data.Ord

sortByLength1 = sortBy (comparing length)

-- [3]

import Data.Function

sortByLength = sortBy (compare `on` length)

As discussed in my previous post, the first was my answer to the exercise in Real World Haskell, the second is from comment 5 by Yair, the third is based on comment 8 by David. Thank you Yair and David for these suggestions.

The three versions are equivalent (although I admit I haven’t tested them for speed). With particular relevance to my previous post, none of these use decorate-sort-undecorate. [2] and [3] are clearly better than [1] as they obviate the need for the wrapper function longer. [2] is my favourite for its readability.

Another thing worth noting is that [2] and [3] omit the parameter a from the definition.

comparing and `on` are new to me, so I’ll outline them briefly here.

comparing

comparing is in Data.Ord:

comparing :: Ord a => (b -> a) -> b -> b -> Ordering
comparing p x y = compare (p x) (p y)

So longer a b is equivalent to comparing length a b.

`on`

Using backticks around a function allows us to use the function as an infix rather than a prefix (see rwh ch 4, section Infix functions p 76), so the following are exactly equivalent:

(compare `on` length)
(on compare length)

on is from Data.Function:

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(*) `on` f = \x y -> f x * f y

I can understand the type signature, and I can see how on compare length a b would fit, but I’m afraid the definition is opaque. I might be able to come back to it after I’ve written about ., $ and &&&. Otherwise, I shall spend some time with my eyes open for different usages of on in the wild. It was very difficult finding information on on (many thanks to a contact on haskell-beginners who pointed me to Hoogle), so I think it will be worth writing up when I can.

Discussion

It took the omission of parameters from [2] and [3] for me to realise that perhaps the thing about Haskell is how much it facilitates combining and mixing functions in different ways. Duh.

decorate-sort-undecorate in Haskell

Wednesday, 24th June, 2009

Real World Haskell
Chapter 3: Defining types, streamlining functions
Section: End of chapter exercises

Exercise 6: Create a function that sorts a list of lists based on the length of each sublist. (You may want to look at the sortBy function from the Data.List module.)

  1. Answering the question
  2. Decorate-sort-undecorate
  3. Type signatures
  4. Further work

Read the rest of this entry »

Haskell: is it a palindrome?

Thursday, 11th June, 2009

Real World Haskell
Chapter 3: Defining types, streamlining functions
Section: End of chapter exercises

Exercise 5: Write a function that determines whether its input list is a palindrome.

The book website has a lot of interesting discussion re this exercise. Most of it revolves around the best implementation, but there are also queries to do with the correct type signature for the function.

The best implementation in terms of speed, memory use, concision and readibility is given below (alas, I came up with the more long-winded implementation).

ispal x = x == reverse x

But I don’t want to talk about that. I want to talk about type signatures again. ispal is a function that takes a list and returns a boolean so, naively, I gave my function this type signature:

[A]  ispal :: [a] -> Bool
     ispal x = x == reverse x

ghci gave me the following error message:

Prelude> :load ispal.hs
[1 of 1] Compiling Main             ( ispal.hs, interpreted )

ispal.hs:2:10:
    Could not deduce (Eq a) from the context ()
      arising from a use of `==' at ispal.hs:2:10-23
    Possible fix:
      add (Eq a) to the context of the type signature for `ispal'
    In the expression: x == reverse x
    In the definition of `ispal': ispal x = x == reverse x
Failed, modules loaded: none.

The correct type signature is as follows:

[B]  ispal :: (Eq a) => [a] -> Bool
     ispal x = x == reverse x

So: What is (Eq a)? What is “context”?

RWH hasn’t told us about (Eq a) yet, and the term is not in the index. Maybe it’ll turn up later in the book, maybe it won’t. Who knows? It can be a nice surprise. Ditto “context”.

In the meantime, Learn You a Haskell and A Gentle introduction to Haskell both explain it well, the latter in more technical language than the former, but they’re saying the same thing (see references below).

The “=>” symbol is a class constraint [1]. The left hand side is a constraint on the right hand side. “Context” is the Haskell technical term for this kind of contraint [3].

In the type signature above, the constraint/context is that the types a must be of type Eq. Items of type Eq support equality testing [1].

So, in the definition of ispal, the use of “==” forces the interpreter to check that x is of type Eq. If there is no type signature, then ghci is free to infer that x is of type Eq. If there is an explicit type signature, then ghci must follow that. In the type signature in [A] above, there are no contraints on a, so ghci cannot infer that a is always of type Eq. And so we get an error.

References

I must say I’m glad these two web books are available, to help me over the deficiencies of RWH.

Learn You a Haskell:
[1] Types and Typeclasses::Typeclasses 101
[2] Making Our Own Types and Typeclasses::Typeclasses 102

A Gentle introduction to Haskell:
[3] Chapter 5: Type classes and overloading

First steps with Pinax

Thursday, 4th June, 2009

Pinax is a web development platform built on top of Django (which is a web development framework). The point of Pinax seems to be that it gathers together and integrates a collection of django applications into one package. You install Pinax and all of a sudden you have a fully functioning ‘default’ social networking website.

Preliminaries for Mac OS X

python-mysql

I’m going to use MySQL with Django. So I need MySQL itself, and the python-mysql interface, python-mysql. If you install mysql and python-mysql from fink, this section may not be necessary.

I installed the Mac OS X MySQL from mysql.com. This meant that the python-mysql from fink didn’t work (it didn’t find mysql & started installing its own). Installing python-mysql from sourceforge didn’t work either: I got a compile error similar to this:

/usr/include/sys/types.h:92: error: duplicate ‘unsigned’
/usr/include/sys/types.h:92: error: two or more data types in declaration specifiers 

From MangoOrange I found the following advice:

Step 4:
In the same folder, edit _mysql.c using your favourite text-editor

4a. Remove the following lines (37-39):

#ifndef uint
#define uint unsigned int
#endif

4b. Change the following:

uint port = MYSQL_PORT;
uint client_flag = 0;

to

unsigned int port = MYSQL_PORT;
unsigned int client_flag = 0;

After a precautionary sudo python setup.py clean, python-mysql will now install with the specified sudo python setup.py install.

PIL

For photo support (e.g. uploading photos to your Pinax homepage), Pinax uses the Python Imaging Library. fink installs PIL to /sw/lib/python2.5/site-packages/PIL/ where MacOSX’s own python can’t find it. I got PIL source from http://www.pythonware.com/products/pil/ and installed that using sudo python setup.py install.

Pinax: install and set up

There’s very little to write here. I followed the instructions and everything worked, …

… except the Locations page in the resulting website. Even here though it showed a very helpful Django error page:

  Exception Type:  	ImproperlyConfigured
  Exception Value:
 	django-locations requires a valid YAHOO_MAPS_API_KEY setting.
   	Please register for a key at https://developer.yahoo.com/wsregapp/
   	and then insert your key into the settings file.

Doesn’t look like I need to worry about that for now. If I want Locations I’ll go get a key, otherwise I’ll uninstall Locations.

Haskell type variables

Monday, 1st June, 2009

Real World Haskell
Chapter 3: Defining types, streamlining functions
Section: A More Controlled Approach

-- file:ch03/MySecond.hs
-- edited excerpt

-- safeSecond :: [a] -> Maybe a

safeSecond [] = Nothing
safeSecond xs = if null (tail xs)
                then Nothing
                else Just (head (tail xs))

-- tidySecond :: [a] -> Maybe a

tidySecond (_:x:_) = Just x
tidySecond _       = Nothing

In December, Helge Stenström made an interesting comment about the above code:

If the type declarations using :: are omitted from safeSecond and tidySecond, they have visually different types, at least in ghci.

safeSecond :: [a] -> Maybe a
tidySecond :: [t] -> Maybe t

Why is it so?

In Hugs both functions have the same type [a] -> Maybe a.

The ghci effect is reproduced in simpler code:

safe xs = head xs
tidy (x:_) = x

In ghci:

*Main> :type safe
safe :: [a] -> a
*Main> :type tidy
tidy :: [t] -> t

I asked about this on Haskell-beginners and got some interesting replies (of which my understanding has a comfortable vagueness). Here is the last reply:

On Sun, May 31, 2009 at 05:42:44PM +0200, Daniel Fischer wrote:
>
> But that has nothing to do with the phenomenon, in the inferred type signatures of
> safeSecond and tidySecond, the ‘a’ resp. ‘t’ are both type variables of kind *.
> The only difference is that in one case the name supply delivered ‘a’ and in the other it
> delivered ‘t’.

I think one source of difference is that ghci tries to maintain type
variable names from declared type signatures. So perhaps one of the
library functions used to define ‘safeSecond’ has an explicitly
declared type signature that mentions ‘a’, and a library function used
to defined ‘tidySecond’ has one that mentions ‘t’.

-Brent

Type signatures in Haskell

Monday, 1st June, 2009

From section Record Syntax (p. 55), RWH starts surreptitiously adding type signatures to its code samples. The code samples work just as well without the type signatures, and RWH does not explain why they are being used (in fact, RWH doesn’t mention these code sample type signatures at all).

Haskell is a typed language, but it uses type inference. So why use type signatures at all? RWH waits until Chapter 5, Section Type Inference is a Double-Edged Sword (p. 117) before telling us.

One reason might be that Haskell might not infer the type you want it to infer. Trivial example:

v :: Int
v = 5

Without the type signature, Haskell will infer that v is of type Integer. OK, that probably won’t make any bridges collapse, but a similar false inference with more complex types might.