The maze book for programmers!
mazesforprogrammers.com

Algorithms, circle mazes, hex grids, masking, weaving, braiding, 3D and 4D grids, spheres, and more!

DRM-Free Ebook

The Buckblog

assorted ramblings by Jamis Buck

aMAZE yourself with Haskell

3 November 2005 — The author provides a report on his progress learning Haskell — 2-minute read

So, as you’ve probably figured out by now, I’ve been learning Haskell. My first actual program now behind me, I thought I’d step up and talk a bit about my thoughts on Haskell so far.

  • Monads still really boggle me. They are my biggest stumbling block so far, and as far as I’m concerned, they are the biggest wart on the face of Haskell. Yah, sure, I understand the idea—you can use Monads to represent a sequence of actions without violating “functional programming”, but it still feels very, very awkward. I definitely have more reading (and practice) to do on this topic.
  • I love how you can define multiple versions of a function and use pattern matching so that the runtime system will choose the correct version based on the value of the parameters. Really slick.
  • I’m still trying to get a practical feel for when to use let and when to use where.
  • Using a strongly typed language feels kind of awkward after so long with Ruby, but that’s not a reflection on Haskell. I must admit that Haskell’s type system is pretty neat.
  • The whole thing with classes and instances is pretty slick, too, though I’m still trying to wrap my brain around it.
  • It feels like you have to pay much closer attention to what you are doing, to avoid cluttering your namespace. Modules help, but once you import them, you’re still stuck with everything in the same namespace. I’ve got to be missing something.
  • I really miss objects! Trying to program something that uses random number generation is a real pain in Haskell, because you have to pass the generator around from function to function. Give me stateful objects anyday, over a purely functional language…but I’m sure that’s mostly my inexperience talking.

Anyway, I’m still working my way through it. It is definitely unlike almost any language I’ve ever learned, although I definitely prefer it over Scheme. I still doubt I’ll convert from Ruby to Haskell, but it’s a new way of thinking about problems, and that is always valuable.

For the curious, here is my first Haskell program. it is a naive random maze generator, which is something I can code in my sleep in a procedural language, but which really stretched me when trying to implement it in Haskell. You Haskell experts out there, please feel free to give me advice on how to make this little program better! (But be gentle…)

Reader Comments

Strangely enough, I felt Neal Stephenson's treatment of Leibniz in his "Baroque Cycle" helped my understanding of monads more than other texts.
Don't worry about monads. You'll hate them now, but learn to love them later. ;-) On the _let_ vs. _where_ question, I almost always use _where_ when writing purely functional code. In monadic code, however, I use _let_ more often because of how it interacts with _do_ notation. To avoid cluttering your namespaces, you can import modules qualified:
import qualified Data.Map as Map
emptySymtab :: Map.Map String Int
emptySymtab = Map.empty
To avoid having to pass things around, use a State monad to do the passing for you. Then create helper functions to work with your state within the monad. Together, the monad and helper functions form a tiny kernel that the rest of your code can use. For example, I modified your maze code to use a tiny monadic kernel to factor out the random-number chores: * "Maze2.hs":http://community.moertel.com/~thor/Maze2.hs * "Diff":http://community.moertel.com/~thor/MazeStateMonad.diff (this is probably more telling) (BTW, if that's your first Haskell code, good job!) In a larger project, you might use monad transformers to layer functionality (like state management) on top of other monads and, in parallel, build up a kernel that provides just the behavior your project needs. That's when the monad goodness kicks in: You can make monads do a lot of heavy lifting behind the scenes. All you have to do is get it right once - when crafting your kernel - and the type system will keep you honest from then on. Cheers. --Tom
Tom, thank-you for the excellent advice and feedback! I'll dissect your contributed Maze.hs and glean as much as I can from it.
Since you're missing objects, I'm wondering why you chose to learn Haskell over OCAML? (I ask this as someone who also wants to learn a functional language and is leaning towards learning OCAML)
Phil, mostly because I've looked (very briefly) at OCaml, and was not immediately impressed. I've also heard from others "in the know" that, although OCaml is interesting, Haskell is cleaner. I do plan on checking out OCaml one of these days, but I chose to start with Haskell.
keep going, this shows the start of 'How monads could be implemented in Ruby!' http://moonbase.rydia.net/mental/writings/programming/monads-in-ruby/00introduction.html
www.ocaml-tutorial.org
cmo, thanks for that link! That (and some pages linked from that) is exactly what I've needed to break into monads. After a full day of reading, I think it's finally starting to make sense.
Hi all, I would like to share with you a problem I encounter whwnever I try to start learning a new programming language: I lack any fantasy about what I should try to code in that new language. And everybody knows that if you just study a language without putting it in practice it's like not studying it at all. Have you got suggestions about how to improve my programming fantasy or any resource that could help me self-making exercies?
flevour, what I usually do is one of two things. I either pick some non-trivial project that I've done before (like the maze-generator), or I pick some little utility I've been meaning to write. Regardless, pick something that is interesting to you. The Haskell tutorials are full of examples that use cloned sheep and binary trees, and while those are useful for demonstrating concepts, they don't really tickle my fancy. Consider choosing a project that uses a database as the backend, or uses a GUI. Or one that is fronted by a web-based UI.
A multi-language resource for useful beginners' code snippets (that may need some optimization here or there) is pleac.sf.net (but also see the Ruby cookbook at www.rubygarden.org). A Ruby script that tries to implement a Haskell feature but still seems to have room for improvement is datatype (cvs.m17n.org/viewcvs/ruby/).
The reason for both let/where being in the language is that Haskell is a commitee language where everybody wants a pice of her/his ideas to show up in the resulting specification IMO.
If you're still missing objects (and inheritance), check out OOHaskell (not O'Haskell) and HList (for heterogeneous lists). You can use similar constructs in your Haskell apps to give an object/inheritance "feel" to your program while still have the benefits of functional programming. While there is research in functional GUI libraries, the most practical Haskell GUI libraries are all bindings to libraries like GTK+ and wxWidgets -- these bindings usually offer an API that is functional with an object/inheritance flavor -- so it is possible to reconcile the two idioms to a degree.
The reason for let and where is that the two do different things (have different scope).

As for Ocaml, it’s fast, but not so user friendly IMHO. The toplevel is poor unless you later find it should be used with ledit or emacs. Ocaml doesn’t provide productive syntax sugar or built-in functions as many as Haskell does, such as list comprehension. I don’t understand why. Yet F# (Ocaml dialect for .Net) seems a promising road with cleaner syntax and other sugar, though it’s still in early stage of development.