Archives

Creative Commons License
This blog is licensed under a Creative Commons License.

Journey into Haskell, part 5

| 2 Comments | No TrackBacks

Haskell may be difficult to start out with, but once things start rolling, they roll fast. Yesterday (real world time, these blog entries are staggered) I had started the first lines of HackPorts, but now things are getting close to done for the first version. It’s not that I’ve written much code, but that it was simple to integrate with other people’s code.

Borrowing all I can

The first thing I wanted to do was avoid dealing with any of Hackage’s data formats, so I cribbed everything I could from the cabal-install package. I actually imported the full source into HackPorts, ripped out its List.hs file, renamed it to my Main.hs file, and then began changing it from a function that prints out a list of available packages, to one that writes the data into properly formatted Portfile entries.

The code does the following bits of work:

  1. Talks to cabal-install and Cabal to get a list of all known packages on Hackage.

  2. For every package, creates a directory named haskell/$package, and then writes information about that package into haskell/$package/Portfile.

  3. As it does this, it fetches the current version’s tarball over HTTP, and uses OpenSSL (directly, through FFI) to generate MD5, SHA1 and RIPEMD160 checksums of the tarball image.

And voilá, a directory populated with 1136 Portfile entries. What’s missing now is the external dependency mapping. As a stub, I have them all depending on port:ghc, but I think there’s sufficient information in the Cabal package info to figure out what the right dependencies should be, both among the Hackage packages themselves and against any external libraries (like OpenSSL).

What I learned

As for my Haskell education, I learned about using Haskell’s very nice FFI mechanism, and had a lot more experience using the IO Monad. An example of using FFI to call out to OpenSSL:

{-# OPTIONS -#include "openssl/md5.h" #-}

foreign import ccall "openssl/md5.h MD5" c_md5
    :: Ptr CChar -> CULong -> Ptr CChar -> IO (Ptr Word8)

I now have access to a c_md5 function, which go directly over to the C library to do its work. Not too shabby!

As for the IO Monad, here is the main function for Hackports:

main :: IO ()
main = do
  createDirectoryIfMissing True "haskell"
  pkgs <- allPackages verbose
  mapM writePortfile pkgs
  putStrLn "Hackage has been exported to MacPorts format in haskell/"

The trickiest part for me was understanding how mapM differs from map. Whereas map takes a list of values and returns a list of values, mapM takes a list of values and returns a list of actions that get invoked in sequence in the current Monad (in this case, IO).

No TrackBacks

TrackBack URL: http://www.newartisans.com/mt/mt-tb.cgi/2551

2 Comments

Something went wrong with the post? Hopefully things get fixed soon. :-)

How do you mean?

Leave a comment

About this Entry

This page contains a single entry by John Wiegley published on March 24, 2009 8:00 AM.

How laziness changes thinking in Haskell was the previous entry in this blog.

Journey into Haskell, part 6 is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Recent Comments

  • yoman: “Barfin”? “Slurping”? “Slime” “Hunchentoot” ??? What in the T.F. world read more
  • Bjorn Tipling: Why would you add instructions for installing an editor when read more
  • Mark Aufflick: sudo port install sbcl +threads If you previously installed sbcl read more
  • Alexander Lehmann: Thank. You. So. Much. – Clisp caused a lot of read more
  • Vetle: Btw, to get support for threading in SBCL, you have read more
  • ifade: I tried the same and get the same answer, but read more
  • Martial Boniou: Hi, I tried to install slime with MacPorts and I read more
OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.25