A Programmer’s Home
Hello and welcome here, comrade. My name is Marc Coiffier, I’m a french 25-year-old computational linguist, humanist, and philosophy, math and music enthusiast who lives in Grenoble, and this is my domain.
In here, you will mainly find reflections on subjects that are fun, beautiful and/or mind-stretching, such as language and theory, Haskell programming and math, a little rhetorics and a lot of magic.
My Programming Religion
One of my trades is to be a Haskell programmer and evangelist, so I would be remiss if I didn’t do my part here to spread the knowledge. The path to understanding wades its way through many trials, but the light that guides you has the shape of a delicate
Haskell is what I would call a definitive programming language, in that it allows you to define what your program is rather than what it does. To help illustrate the difference, the
main function in Haskell isn’t really a function. Instead, it is what Haskellers sometimes call an “IO action”, which is an action that interacts with the Real World and returns a value. In
main’s case, the returned value is of type
(), which means it doesn’t contain any data (actually, it contains one bit, so it would be more precise to say it contains a little).
Defining everything as a value allows everything to be passed around as easily as an integer or a data structure. In fact, there is barely any notion of executing code in Haskell. All you think about is evaluating values, which in practice are much easier to think about than any kind of sequential process that might yield the same values.
Actions are values, and functions are values. Unions are values, and aggregates are values as well. Obviously, basic types like
integer also contain values. An example of how this allows you to write amazing code are the
unless functions (that’s right, functions, not builtins). They are defined thusly :
when b a = if b then a else return () unless = when . not
And here is how they may be used :
when (filename /= ".") (do str <- readFile filename putStrLn (take 40 str) return ()) unless (null queryResults) (do putStrLn ("Result : "++show (head queryResults)))
Pretty awesome, right ? What if I told you that this is just barely scratching the surface of what definitiveness can get you ? Here is an example of what real Haskell code looks like, the same two expressions as above :
when (filename /= ".") $ readFile filename >>= putStrLn . take 40 for_ (headMay queryResults) $ \result -> putStrLn ("Result : "++show result)
You’ll notice that the real Haskell code is quite a bit shorter, and still maintains a kind of readability. The first one reads like this : when filename is not “.”, read that file, then print its first 40 characters. The second one is harder to read if you are not familiar with the Maybe datatype, which is like a list of one or zero elements. In that light, the
for_ function is used to iterate through the first 1 elements of the query result. Haskell being a lazy language, the rest of the list will never be evaluated, as it is not needed.
These are but toy examples, but Haskell goes much deeper than that and will enable you to write extraordinary things. Things like a web server, a 3D Pong implementation, a monadic Makefile implementation, all in less than 200 lines of code each.
Oh, and Haskell, by its very definition, makes writing parallel and concurrent code a cinch. Basically, every value is like an imperative Promise, it yields it value only once, caching the result for future reads.
Still interested ? Install the Haskell Platform, Learn You A Haskell For Great Good and get hacking !