Recent PhotosCalendar
ArchivesQuicksearch |
Wednesday, May 23. 2007Real-World Haskell
Today, Bryan O'Sullivan, Don Stewart, and I are announcing a new book we're working on with O'Reilly: Real-World Haskell. I'm excited about the book and about working with Bryan and Don on this project.
O'Reilly has agreed to publish this book under a Creative Commons license! We plan to post drafts of chapters incrementally at the book's website, seeking feedback from readers and reviewers as we go. Haskell makes a great practical parsing and scripting language, but this aspect of it has been under-documented. I look forward to helping change that! Saturday, March 3. 2007
Posted by John Goerzen
in Programming at
08:37
Comments (3) Trackbacks (0) Defined tags for this entry: haskell
A better environment for shell scripting
Shell scripts are good for a lot of things. It's quick and easy to design shell scripts that take input from one program, pass it to another program, munge it for filenames, etc.
But there are a few drawbacks to shell scripts. The #1 drawback, in my opinion, is that it is extremely difficult to get quoting and escaping right. I often see things like $@ in shell scripts (breaks if a parameter has a space in it). I also see people failing to check for errors properly (set -e helps that). It's also difficult to do a more modern style of exception handling (do a sequence of actions in a temporary directory, and always remove that directory, even if there's an error, but stop processing and propogate the error). Command-line parsing is esoteric and odd, even with getopt. That's not to say that it's impossible to make a secure shell script that handles filenames with spaces in them properly. Just that it's difficult, and makes using common operators like backticks difficult. Awhile back, I toyed with the idea of making Haskell a shell scripting language. This week, I spent some time to make this a reality. I released HSH, a shell scripting environment for Haskell. HSH makes it easy to run shell commands, set up pipelines, etc. straight from Haskell. You can either use simple strings to invoke commands (they'll be passed to sh -c), or you can specify arguments as a list (like exec...() takes), which eliminates the strange filename problems. But the really cool thing is that HSH doesn't just let you pipe from one external program to another. It also lets you pipe to/from pure Haskell functions. Yes, you can pipe the output of ls -l straight into a Haskell version of grep. I've found it to be very nice, especially for more complex processing tasks. I put these simple examples on the HSH homepage: run $ "echo /etc/pass*" :: IO String -> "/etc/passwd /etc/passwd-" runIO $ "ls -l" -|- "wc -l" -> 12 runIO $ "ls -l" -|- wcL -> 12In this example, wcL is a pure-Haskell line-counting function. The results were surprising. According to SLOCCount, porting hg-buildpackage from a shell script to a HSH script achieved a 20% reduction in source lines of code. And at the same time, gained better error handling, better safety of filenames, better type safety (compile-time type checking), etc. Yet it does exactly the same thing in almost exactly the same way. Even greater savings will occur too. I decided to reimplement a small part of sed just for fun, and that code is still in my tree. If I removed that and replaced it with a call to sed as in the shell version, that would probably buy another 5% savings. I didn't really expect to achieve a reduction in lines of code. I thought that I'd be lucky to come close to breaking even. After all, who'd expect something other than the shell to be better at shell scripting? I don't know if these results are generalizable, but I'm really excited about it. Thursday, February 8. 2007
Posted by John Goerzen
in Programming at
06:56
Comment (1) Trackbacks (0) Defined tags for this entry: haskell
Haskell Time Travel
There is something very cool about a language in which the easiest, most direct way to explain how it solves a problem is to say, "When we pass the output of [this function] into the input for the oracle we are actually sending the data backwards in time. So when [the code] queries the oracle we get a result from the future."
Sweet. The story goes on to say, however, "Time travel is a very dangerous business. One false move and you can create a temporal paradox that will destroy the universe (which in this case means that the computation will diverge). When programming with values from the future, it is important never, never, to do anything with the values that might change the future. This is the temporal prime directive." Sunday, December 3. 2006
Posted by John Goerzen
in Programming at
23:53
Comments (2) Trackbacks (0) Defined tags for this entry: haskell
The Haskell Blog Tutorial
The first installment of Mark C. Chu-Carroll's Haskell tutorial series went up last week.
It begins this way: Before diving in and starting to explain Haskell, I thought it would be good to take a moment and answer the most important question before we start: Farther down: So what makes Haskell so wonderful? Or, to ask the question in a slightly better way: what is so great about the pure functional programming model as exemplified by Haskell? An interesting and though-provoking article, even for someone that's been using Haskell for more than 2 years now. (Yikes, I had no idea it was that long) You can also see all his posts on Haskell, which include a couple more installments. Tuesday, September 5. 2006
Posted by John Goerzen
in Programming at
05:58
Comments (3) Trackbacks (0) Defined tags for this entry: haskell
Another Haskell Solution to Lars' Problem
Yesterday, I posted an 18-line solution to Lars' language problem. One problem with it was that it was not very memory-efficient (or time-efficient, for that matter). In other words, it was optimized for elegance.
Here is a 22-line solution that is much more memory-efficient and works well with his "huge" test case. Note to Planet readers: Planet seems to corrupt code examples at times; click on the original story to see the correct code. The main change from the previous example to this one is using a Map to keep track of the frequency of each word. Monday, September 4. 2006
Posted by John Goerzen
in Programming at
11:58
Comments (6) Trackback (1) Defined tags for this entry: haskell
A Haskell solution to Lars' Problem
Thanks to a little glitch in planet, one of Lars' posts from 2004 came to my attention. In it, he proposes a test for language benchmarking:
Read text from the standard input and count the number of times each word occurs. Convert letters to lower case. Order the words according to frequency, words with the same frequency should be ordered in ascending lexicographic order according to character code. Print out the top N words, where N is a decimal number given on the command line. Each output line must contain the count, a space, and the word (in lower case), and end in an ASCII LINE FEED character. Output must contain exactly N such output lines and no other output lines. He provides a tarball with sample implementations in C, Python, and Shell. His C code is 183 lines long, Python 57, and Shell 11. The specs for this test seem particularly suited for shell. I wrote a version in Haskell, commented and formatted approximately the same as his Python version, but using an algorithm more like the shell version. It comes in at 18 lines. Here it is: Taking a look at this, one thing that might strike you is the function composition in main. This takes the output from one function and feeds it into the next -- and the Haskell syntactic sugar for this makes it look a lot like pipes in the shell version. The interact call takes, as a parameter, a function that takes a string and returns a string. interact supplies stdin as the input and prints the output to stdout. Note that, since Haskell is lazily, this does not mean buffering up the entire input or output -- it is read and written on demand. The rest of the functions are also standard in Haskell, and you can find them in the index to the library reference if you want to learn more. I understand and agree that short code doesn't necessarily mean good code, but I think that Haskell provides a very elegant and expressive solution to many problems -- one that also happens to be remarkably concise. Updated 9/4: Changed isLower to isAlphaNum to fix a bug, and removed unnecessary Data.Map import Sunday, September 3. 2006
Posted by John Goerzen
in Programming at
21:15
Comments (0) Trackbacks (0) Defined tags for this entry: haskell
Lazy big-O and Haskell Answers
First, Evan has a host of interesting articles about Haskell, and I found his lazy big-O article particulary interesting.
Next, Eric Warmenhoven has recently taken up Haskell and posted some Haskell questions on his blog. Eric, here are some answers for you. First, regarding shared libraries. While Haskell can be compiled to machine code, and GHC is a popular way to do that, a standard C way of representing information about a library (.h and .so files) is not really rich enough for Haskell. Consider, for instance, that functions may accept arguments of a wide range of types (or even things such as lists of any type). Haskell also performs type checking, and thus must know the type of arguments a function expects, as well as its return type, at compile time. So you do not generally compile Haskell code directly to .so files, but rather use the compiler's module or package support to do that. See Cabal for more information on packages. Through the FFI (Foreign Function Interface), it is possible to both call into C and be called from C with Haskell code, if that's where you want to go. It is actually easier in Haskell than in any other high-level language I've dealt with before. Regarding circular module deps -- I've never used them and can't really comment. I can say, though, that the .boot files are internal files created by GHC. Regarding practical stuff in tutorials -- I share your complaint there. I have found a few that are better than the others: Yet Another Haskell Tutorial, and Haskell: The Craft of Functional Programming, 2nd ed., by Simon Thompson. Several of us are working intermittently on a project called Haskell V8 -- take a look and darcs send me patches! I would say that Haskell's I/O system is the most powerful I've seen in many ways -- especially with regard to laziness -- and in the upcoming GHC 6.6 release, it will be both lazy *and* blazingly fast. Very nice. There isn't much Debian-specific documentation, but there is a draft policy and a mailing list (link to it is in the policy doc). Hope this helps! |
The ChangelogMost Popular TagsSyndicate This BlogBlog Administration |
|||||||||||||||||||||||||||||||||||||||||||||||||

Comments
Fri, 09.05.2008 15:51
We use Accurev here at work, s o let me try that. Well, I do know that several airlines actually use Accurev and [...]
Thu, 08.05.2008 16:34
Continuus Airlines: This a irline started as a skunk-work s project in Sweden that was s old as a "sort of versio [...]
Wed, 07.05.2008 07:43
Just a small update: The re dmine forums have been moved t o redmine.org 4 days after you r post: http://rubyfo [...]
Mon, 05.05.2008 14:49
What the hell are you guys tal king about? Is it really that bad? Can't programmers google anymore? Swap Caps and E [...]
Sun, 04.05.2008 11:57
I use the Google Browser Sync firefox extension on all 3 of my computers. It syncs everyth ing: bookmarks, cookies, [...]
Sun, 04.05.2008 09:32
I've been thinking about setti ng up an ikiwiki site to hand le my bookmarks. I'm currentl y using a wiki page on [...]
Sun, 04.05.2008 07:53
I guess what I would say is th at PDF *can* faithfully reprod uce documents, but doesn't gua rantee that it always wi [...]
Sun, 04.05.2008 07:51
I agree with you; I have some file:/// URLs bookmarked. T he del.icio.us has a syncing a lgorithm, and I have fou [...]