What's a good (easy) exercise to practice some Haskell programming?

Don’t say Project Euler.

I dunno, but the only haskell “programming” I’ve done is setting up xmonad - the config file(s) for xmonad are pure haskell. On the one hand you’ll be writing something that’s actually useful. On the other, unless you’re running X11 you’ll probably not have any use for it.

Kinda like learning lisp by using Emacs. :slight_smile:

Ha! I’ve been using Emacs for more than a decade and my Elisp is still limited to tweaking my .emacs file.

I hadn’t heard of Xmonad before. It looks interesting. Right now I’m using whatever the default WM on Fedora Core is (I’ve long since stopped paying attention to window manager configs.)


Don’t really have any specific ideas to contribute, but what I’ve always done myself is to set a goal to write something I’d actually use. Whether it’s some sort of program you want that doesn’t exist, doesn’t exist cheaply, doesn’t do exactly what you want, etc… Many moons ago when I was first learning UNIX, before the days of Linux and before open source really picked up steam, I ran a BBS. I acquired an AT&T 3B1 and wanted to move my BBS onto that, so I learned C by writing a pretty bare-bones BBS software.

Several years later I wanted to learn Perl. We had some specific needs for network monitoring applications at work, so I decided to write a network monitoring application.

Some folks do better starting off small, and moving onto bigger things. YMMV but I tend to do better with a sink-or-swim approach, just jumping in and figuring out how to write something useful like that. Of course I often pick up some bad practices along the way, and then go back and refine the code, but I find it helps to have a concrete goal like that. I just could never get seriously into coding when it’s just a program written as an exercise.

Again YMMV, good luck!

Try solving the stable marriage problem using purely functional data structures.

I wouldn’t even know where to begin on this one, since the algorithm that’s defined in the article seems to rely on mutable state by definition.

(Here come 12 dopers to say “of course it doesn’t,” with explanations that fly way over my head.)

I have a strong feeling that I am never, ever going to get this shit. I’m gonna go feel sorry for myself while I write some unrelated code that mortals can comprehend.

OK I’m done acting like a whiny bitch.

I came up with some types and test data, and a function to return a tuple which indicates a proposal. But I have no idea how to keep track of who has proposed to whom and who has been rejected by whom since I’m not allowed to use variables.

data Sex = Sex Char deriving Show

male   = Sex 'M'
female = Sex 'F'

data Name   = Name [Char]      deriving Show

data Person = Person { 
    sex    :: Sex,
    name   :: Name,
    people :: [Person]
} deriving (Show)

man :: [Char] -> [Person] -> Person
man n ps = Person { sex = male, name = Name n, people = ps }

woman :: [Char] -> [Person] -> Person
woman n ps = Person { sex = female, name = Name n, people = ps }

alice  = woman "Alice"  [ alfred, brian, chuck ]
bonnie = woman "Bonnie" [ brian, chuck, alfred ]
carla  = woman "Carla"  [ alfred, chuck, brian ]

alfred = man "Alfred"   [ alice, bonnie, carla ]
brian  = man "Brian"    [ bonnie, alice, carla ]
chuck  = man "Chuck"    [ carla, alice, bonnie ]
propose :: Person -> (Person, Person)
propose p = (p, head(people p))

I need hints.

Stylistic hints:

Instead of

data Sex = Sex Char deriving Show

male   = Sex 'M'
female = Sex 'F'


data Sex = Male | Female deriving Show

Instead of

data Name   = Name [Char]      deriving Show


type Name = String

(Strings in Haskell are literally a list of chars).

Instead of

man :: [Char] -> [Person] -> Person
man n ps = Person { sex = male, name = Name n, people = ps }

woman :: [Char] -> [Person] -> Person
woman n ps = Person { sex = female, name = Name n, people = ps }


person :: Name -> Sex -> [Person] -> Person
person nm sx ppl = Person { sex = sx, name = nm, people = ppl }

I’ll have to read the problem to be able to give more useful hints.

As to how best to learn it: I learned functional programming with Standard ML (Paulson’s book is good, but I also had an undergraduate course). Learning Haskell was then quite straightforward (though I’m still not sure about more advanced stuff like arrows, idioms and GADTs). The best way is to just pick up a textbook and work through the exercises. Running HSLint on your code will also show you how to improve your style.

OK, I’ve looked at the algorithm. I suggest you change your person datatype to:

data Person = Person Sex Name [(Person, Int)]

This is because (for the time being) Haskell records aren’t very easy to work with, unless you use GHC extensions. The [(Person, Int)] is a list of potential matches, with an integer preference.

You first need a list of men, and a load of available women:

alice = person Female "Alice"  [ (alfred, 1), (brian, 2), (chuck, 3) ]
bonnie = person Female "Bonnie" [ (brian, 3), (chuck, 1), (alfred, 2) ]
carla = person Female "Carla"  [ (alfred, 3), (chuck, 2), (brian, 1) ]

men = [person Male "Alfred"   [ (alice, 1), (bonnie, 2), (carla, 3) ].
             person Male "Brian"    [ (bonnie, 1), (alice, 2), (carla, 3) ],
             person Male "Chuck"    [ (carla, 1), (alice, 3), (bonnie, 2) ]]

You now need a function that finds a Person’s highest matched mate that is still “free” (I’m using the assumption that if a person is in the list of [(Person, Int)] then they are “free”). This will have type:

findHighestRankedMate :: Person -> Maybe (Person, Person)

(The Maybe is needed because there may not be a free mate left! The second Person in the tuple is the input Person with the highest ranked free mate removed from their preference list).

The rest of the problem will be solved recursively. The main function will probably have type:

stableMarriage :: [Person] -> [(Person, Person)]

Try implementing the findHighestRankedMate function first.

PS, another great resource for beginner Haskell programmers is the Haskell Cafe and Haskell Beginners mailing lists. They’re very active, and people are only too happy to help.

Thanks for the tips, Captain. I will revisit the problem when I get home from work tonight. (Alas, no fun functional programming here. :frowning: )

By the way, you may like this website, which has a number of small problems with multiple solutions in different languages. Some of these problems look ideal for learning Haskell (like generating Huffman codes), and there’s already Haskell solutions there for you to look at.