Tuesday, June 30, 2009

FFI: calling into kernel32.dll

Calling the Win32 API function GetComputerName makes for a nice demonstration of combining Haskell's FFI, hsc2hs, and Cabal.

The front matter:

{-# LANGUAGE ForeignFunctionInterface #-}

module Win32.Kernel32 (getComputerName) where

import Control.Monad (when, unless)
import Data.Bits ((.|.))
import Foreign.Marshal.Alloc (alloca)
import Foreign.Ptr (nullPtr)
import Foreign.Storable (peek, poke)
import System.Win32.Types (DWORD, LPDWORD, LPTSTR, LPVOID,
                           peekTStringLen, peekTString, withTString)

#include <windows.h>
With hsc2hs, it's possible to #include C headers and use constants in Haskell programs, as we'll see below.

Now to get hold of a few entry points in kernel32.dll. The types defined in System.Win32.Types are handy:

foreign import stdcall unsafe "GetComputerNameW"
  win32_getComputerName :: LPTSTR -> LPDWORD -> IO Bool

foreign import stdcall unsafe "GetLastError"
  win32_getLastError :: IO DWORD

foreign import stdcall unsafe "FormatMessageW"
  win32_formatMessage :: DWORD
                      -> LPVOID
                      -> DWORD
                      -> DWORD
                      -> LPTSTR
                      -> DWORD
                      -> LPVOID
                      -> IO DWORD
Note the use of the stdcall calling convention and that we're calling the wide-character versions.

GetComputerName takes two parameters, a pointer to a character-buffer and a pointer to an in-out DWORD (in: capacity; out: used). On the Haskell side, this means a couple of allocations, initialize the length parameter, call GetComputerName, and read the result:

getComputerName :: IO String
getComputerName =
  withTString maxBuf $
    \buf ->
      alloca $ \len -> do
        poke len (fromIntegral maxLength)

        success <- win32_getComputerName buf len
        unless success $ failWithLastError "GetComputerName"

        len' <- peek len
        peekTStringLen (buf, (fromIntegral len'))
    maxBuf = replicate maxLength '\0'
    maxLength = #const MAX_COMPUTERNAME_LENGTH
The #const bit at the end tells hsc2hs to substitute the value of the C preprocessor symbol MAX_COMPUTERNAME_LENGTH.

If all goes well, GetComputerName returns non-zero, but we'd like to handle cases when things go wrong. In the Win32 API, we'd call GetLastError and convert the error code to a human-readable diagnostic with FormatMessage:

failWithLastError :: String -> IO a
failWithLastError name = do
  code <- win32_getLastError
  withTString errbuf $
    \buf -> do
      gotmsg <- win32_formatMessage flags
                                    (fromIntegral errlen)
      fmtcode <- win32_getLastError
      when (gotmsg == 0) $
        fail $ name ++ " failed: " ++ show (code, fmtcode)

      msg <- peekTString buf
      fail $ name ++ ": " ++ filter notEOL msg
    errbuf = replicate errlen '\0'
    errlen = 300
    lang = 0
    notEOL c = c /= '\n' && c /= '\r'
FormatMessage can fail too, so in that case, the poor user is stuck with a couple of opaque error codes. Otherwise, peekTString copies the formatted error message for use with fail. Note also that Win32's FormatMessage is variadic, but this wrapper does not take advantage, instead passing a canned null pointer.

Having nice error messages can be sort of helpful with programming errors such as forgetting to initialize the length parameter in a call to GetComputerName:

$ cabal test
test: user error (GetComputerName: The file name is too long.)
The code above lives in a file named Kernel32.hsc. The package definition (.cabal file) points to the module name, and when Cabal finds the .hsc extension, it transparently runs the code through hsc2hs:
  hs-source-dirs:  src
  exposed-modules: Win32.Kernel32
  build-depends:   base, Win32
  extensions:      ForeignFunctionInterface
  ghc-options:     -Wall
The package includes a simple test that calls getComputerName and prints the result to the standard output, so the following sequence of commands should remind you of your machine's name:
cabal configure -ftest
cabal build
cabal test
The code is also available on GitHub.

Monday, June 29, 2009

Cleaning up your Haskell imports

Explicit imports have a couple of benefits. For one, doing so reduces compile times with ghc. Another is giving a hand to your future self (or other maintainers) and especially to those who are reading your code to learn. We've all been there: scratching our heads wondering, ‘Where does that function live?’ Yes, ghci's :info command and Hoogle are your friends, but explicit imports right there in your code will give the answer in a snap.

Neil Mitchell calls explicit imports “needlessly verbose,” certainly a fair point in the context where he made it, so this is a matter of polish, not strict necessity. There's also a certain aspy-appeal to it.

The -ddump-minimal-imports option to ghc writes the cleaned-up list to M.imports, where M is the module being compiled. For example, consider the following code that finds anagrams in a dictionary file:

module Main where

import Control.Arrow
import Control.Monad
import Data.Char
import Data.List
import Data.Map hiding (filter, map)
import System.Environment
import System.Exit
import System.IO

usage :: IO a
usage = do
  me <- getProgName
  hPutStrLn stderr $ "Usage: " ++ me ++ " [ dictionary ]"
  exitWith (ExitFailure 1)

main :: IO ()
main =
  getPath >>= readFile >>= mapM_ (putStrLn . unwords) . sorted
  where sorted = sort . map sort . anagrams . lines

anagrams :: [String] -> [[String]]
anagrams words = filter ((>1) . length) equiv
  where equiv = elems $
                  fromListWith (++)
                    [ (normal w, [w]) | w <- words ]
        normal = sort . map toLower

getPath :: IO FilePath
getPath = getArgs >>= go
  where go [path] = return path
        go []     = return "/usr/share/dict/words"
        go _      = usage
To get the minimal set of imports:
$ ghc-6.10.3 -ddump-minimal-imports --make anagram.hs 
$ cat Main.imports
import System.IO(IO, FilePath, putStrLn, readFile, hPutStrLn,
import Data.Map(elems, fromListWith)
import Control.Arrow()    -- Instances only
import Control.Monad(Monad(return, (>>=)), mapM_)
import Data.Char(String, toLower)
import Data.List((++), filter, map, length, lines, unwords, sort)
import System.Environment(getArgs, getProgName)
import System.Exit(ExitCode(ExitFailure), exitWith)
Although nice, the result is less than satisfying. The cuddled lists are ugly. The imports are in an odd order. Having to do run a separate compilation by hand followed by copy-paste, as opposed to automatically à la Eclipse's organize imports for Java, is a bit of a pain.

Notice that although Control.Arrow is unnecessary, it remains in the “minimal” set with an empty import list. Its presence is an artifact of the list comprehension being equivalent to

map (normal &&& (:[])) words
Cool, yes. Readable, not so much.

Note also there's an open ticket against ghc concerning the interaction between -ddump-minimal-imports and qualified imports.

Saturday, June 27, 2009

Installing curl from hackage on Cygwin

On a Windows machine, I upgraded to ghc-6.10.3 and was in the process of building and installing libraries from hackageDB, Haskell's CPAN—hmm, or should that be Haskell's CTAN?

I had already upgraded cabal-install:

$ cabal --version
cabal-install version 0.6.2
using version of the Cabal library
I was unsuccessful installing curl from a cmd.exe prompt:
c:\>cabal install curl
Resolving dependencies...
Configuring curl-1.3.5...
cabal: Error: some packages failed to install:
curl-1.3.5 failed during the configure step. The exception was:
sh: runGenProcess: does not exist (No such file or directory)
Fair enough: installing curl requires a real shell, so let's try from inside Cygwin:
$ cabal install curl
Resolving dependencies...
Configuring curl-1.3.5...
checking for gcc... /cygdrive/c/ghc/ghc-6.10.3/gcc
checking for C compiler default output file name... a.exe
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... .exe
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether /cygdrive/c/ghc/ghc-6.10.3/gcc accepts -g... no
checking for /cygdrive/c/ghc/ghc-6.10.3/gcc option to accept ANSI C... none needed
checking how to run the C preprocessor... /cygdrive/c/ghc/ghc-6.10.3/gcc -Bc:/ghc/ghc-6.10.3/gcc-lib -Ic:/ghc/ghc-6.10.3/include/mingw -E
configure: error: curl libraries not found, so curl package cannot be built
See `config.log' for more details.
cabal.exe: Error: some packages failed to install:
curl-1.3.5 failed during the configure step. The exception was:
exit: ExitFailure 1
I already installed Cygwin's curl-devel package, so maybe I needed to help the linker along (note the DOS-ish paths because the mingw gcc bundled with ghc doesn't know about Cygwin):
$ cabal configure \
        --extra-include-dirs=c:/cygwin/usr/include \
Same failure as above.

Maybe if I build the package by hand:

$ cd /tmp

$ cabal fetch curl
Resolving dependencies...
No packages need to be fetched. All the requested packages are already cached.

$ cabal unpack curl
Unpacking curl-1.3.5...

$ cd curl-1.3.5/

$ cabal configure --extra-lib-dirs=c:/cygwin/usr/lib --extra-include-dirs=c:/cygwin/usr/include
Resolving dependencies...
Configuring curl-1.3.5...
checking for gcc... gcc
checking for C compiler default output file name... a.exe
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... .exe
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking how to run the C preprocessor... gcc -E
configure: creating ./config.status
config.status: creating curl.buildinfo
cabal.exe: Missing dependency on a foreign library:
* Missing C library: curl
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
No dice.

I tried fiddling with the environment (CC, CFLAGS, LD, and LDFLAGS) and running ./configure by hand, but that produced only frustration.

"If you can't beat 'em, join 'em," I said, and

$ cp /usr/lib/libcurl.a /cygdrive/c/ghc/ghc-6.10.3/gcc-lib/

$ cabal install curl --extra-include-dirs=c:/cygwin/usr/include
/usr/bin/ar: creating dist\build\libHScurl-1.3.5.a
Installing library in C:\Program Files\Haskell\curl-1.3.5\ghc-6.10.3
Registering curl-1.3.5...
Reading package info from "dist\\installed-pkg-config" ... done.
Writing new package config file... done.

Thursday, June 25, 2009

Find GPS Info

A coworker asked if I knew of a way to convert batches of hundreds of street addresses to lat/lons. The Geo::Google module on CPAN looked promising at first, but it seems to have fallen into disrepair. A solution was straightforward with the Google Maps API.

Give it a spin! Enter street addresses in the top textarea (one per line), click Search, and you should get a CSV-ish output on the bottom.

Wednesday, June 24, 2009

The man of understanding

A rebuke goes deeper into a man of understanding
    than a hundred blows into a fool.

Whoever restrains his words has knowledge,
    and he who has a cool spirit is a man of understanding.

Proverbs 17:10,27

A police investigator?

We were going to investigate an incident involving vandalism and a possible pet poisoning at someone's home.

My partner was Giancarlo Esposito (whose name I had to hunt and found thanks to mixedfolks.com), and he was the one who took the lead. That made it a somewhat typical detective story: smooth veteran stuck with a nerdy white guy who's fresh on the job.

In the dream, I seemed to know that our destination belonged to Mark Dominus (author of the enlightenning Higher-Order Perl), and I was concerned that the crime against their property was related to his children being biracial.

The real Dominus lives in Philadelphia, but the setting of his house didn't seem like Philadelphia: instead it was cookie-cutter suburbia. The big house with its ornate, frumpy furniture, rugs, and wallhangings was better suited for someone's grandparents than how I picture him living.

Giancarlo questioned him about their dog as to whether Dominus encouraged some behavior or other. This was the best part of the dream but about which my recall is disappointingly bad. Imagine Philip K. Dick had written The Jerk: Dominus sat back in his chair and followed down a long verbal rabbit hole about the dog actually being a wumpus who believed he was a house but was really something else and how Dominus himself was a cow who imagined being a man but with similar multi-layer misgivings.

I asked smarmily, "Did you get all that in your little notebook?"

He showed us the damage to the nearly floor-to-ceiling picture window that wrapped around one of the front corners of the house. Many of the panes at the top were shattered. I asked if he knew who might have done it, and he remarked about neighborhood kids (who probably wouldn't stay off his lawn and all). Someone speculated that it may have been "random dumbassery."

I look up again and now the window is stuffed with what appeared to be lots of crumpled disposable drop cloth. I asked if he'd like us to help with more patchwork (I was thinking of a tarp on the outside), but he declined saying the guy coming tomorrow would fix it properly.

But I stopped the pain meds a couple of days ago! Where'd that come from?

Tuesday, June 23, 2009

Setting up a simple test with Cabal

With the Cabal build and packaging system for Haskell, add a simple test program to your build with a couple of easy steps.

First, add the following to your project's cabal file:

Build-Type: Custom


flag test
  description: Build test program.
  default:     False

Executable test
  hs-source-dirs:  src, test
  other-modules:   MyModule1, MyModule2
  main-is:         Main.hs
  build-depends:   base
  if !flag(test)
    buildable:     False
When enabled (via cabal configure -ftest but otherwise off), this builds an extra program called test.

The custom build type gives you more flexibility in your setup script, so add code such as the following to Setup.hs:

main = defaultMainWithHooks hooks
  where hooks = simpleUserHooks { runTests = runTests' }

runTests' :: Args -> Bool -> PackageDescription -> LocalBuildInfo -> IO ()
runTests' _ _ _ lbi = system testprog >> return ()
  where testprog = (buildDir lbi) </> "test" </> "test"
When you run cabal test, it will kick off your test program whose source is in test/Main.hs.

This approach has a few drawbacks. Users must explicitly enable the test builds. Building the test program entails rebuilding the other libraries in your package. Installing from a -ftest configuration will also install your test program.

Thursday, June 18, 2009

On to recovery

Thanks, everyone, for checking up on me.

I had hip surgery this morning with the doctor who pioneered the procedure for the labrum damage I had. Everything seemed to have gone well. Dr. Byrd even gave me a DVD of my surgery! I assume it's video from the scope, so stay tuned for future post with some nice gory clips!

I'm sore of course, but the drugs are good. I have this device called a Game Ready that's a sleeve around my upper leg and a pump that compresses the area with ice-cold water. It's supposed to speed up recovery, but I'll be on crutches for 8 weeks—no driving for 6.

I have a followup visit in the morning and tort^H^H^H^Hphysical therapy after that.

My wife has been a wonderful caretaker. I don't know how I married so well!

Tuesday, June 16, 2009

RIP, Heather

I learned today that a high school classmate died yesterday from "health complications." At our reunion five years ago, she had recently been hospitalized for taking too much Tylenol over an extended period. I think it did a number on her liver, but I don't know whether that was connected to her death.

The sad news came by way of Facebook: her husband posted a long status message. The widow of one of my fraternity brothers did the same thing. Another friend from college was posting updates from the delivery room (e.g., "still 4 cm, 80% effaced and started having contractions this morning right before being admitted. Now hooked up to IV and pitossin just started 5 min ago.") I'm not sure what to make of the combination.

Heather was a schoolmate of mine from much farther back than high school: she and I sat next to each other in Mrs. Powell's first-grade class. I can remember her seventh or eighth birthday party at one of Mobile's many skating rinks. She was so young, too young to die. She's my age, after all! I wouldn't mind if it turned out to be a sick prank. I guess that's a mild form of denial.

In pace requiescat.

Monday, June 15, 2009

FFI: C function taking pointer to array

Say you want to call the following C function from Haskell: The parameter tarray is a pointer to an array of floats. From C, you'd use it along the following lines:
    float times[2];
    printf("user time=%f, system time=%f\n", times[0], times[1]);
But in the Haskell world, even though such destructive updates are anathema, we can still talk back and forth.

First, we enable the Foreign Function Interface language pragma:

> {-# LANGUAGE ForeignFunctionInterface #-}
Then some front matter:
> module Main where
> import Foreign (Ptr)
> import Foreign.Marshal.Array (allocaArray,peekArray)
> import Control.Monad (mapM_)
We let Haskell know about the C function we want to call with an import declaration:
> foreign import ccall etime_ :: Ptr Float -> IO Float
To prepare for the call to the C function, allocaArray creates a new buffer and passes a handle to it (ta in the example below) to an action that calls etime_, pulls the data with peekArray, and returns these values along with the value returned from etime_ in a tuple:
> etime :: IO (Float, Float, Float)
> etime = do
>   allocaArray 2 $ \ta -> do
>     t <- etime_ ta
>     [user,sys] <- peekArray 2 ta
>     return (t,user,sys)
Use the etime action as in the following example:
> main :: IO ()
> main = do
>   (t,user,sys) <- etime
>   putStrLn $ "user time:    " ++ show user
>   putStrLn $ "system time:  " ++ show sys
>   putStrLn $ "process time: " ++ show t

Saturday, June 13, 2009

Helicopters and jets

I looked out a window into my back yard where a small helicopter sat. I think it was mine even though the back yard didn't look like the one at our current house or any where I've lived. Another helicopter was flying very low and slightly erratically so as to jostle my craft with its downdraft. Did I mention loud?

‘I should call the FAA,’ I thought, ‘that's harassing flight.’ (I don't guess they have a game warden at the FAA.)

My neighbor had a small jet in his back yard, and the helicopter was also buzzing it. By this time, my wife was watching the scene with me. Next thing I know, the jet was in the air (must’ve come with the vertical takeoff feature) at about the same height as the helicopter.

“I hope it doesn’t hit the house,” Sam said, but as it flew away, we heard a thud from the roof.

We ran out to the back yard. We didn't seem concerned about the helicopter any longer, so maybe it departed too. The yard and house now seemed to be our current house, and we inspected the roof for damage. Because of the recent hail, we have a nice new roof in real life, but in the dream, the roof was old and faded with a comically ghetto patch-job of all kinds of different materials and colors. For example, in one spot there was a tannish piece of linoleum with a faux tile look next to maybe a tar patch.

Thursday, June 11, 2009

A huge step!

As of today, more than a majority of the U.S. House of Representatives have cosponsored the Federal Reserve Transparency Act, but Parker Griffith is still taking a wait-and-see approach. This bill matters to ordinary Americans because all government activities should take place in sunlight. The Fed's easy-money policies are destroying the value of the dollar, which will cause increased prices for everyday goods such as gas and groceries, and destroying families' balance sheets by enticing households to go deeper into debt.

Ron Paul's staff issued a press release heralding the achievement.

Why hasn't the Fed already opened its books for all to see? What do they have to hide?

Wednesday, June 10, 2009

Tuesday, June 09, 2009

But I'm still a spring chicken!

I've been trying to duck it for a couple of years now, but it doesn't look like there's any way around it. I met with a surgeon today, and after reviewing MRI and CT studies, he recommends a laproscopic procedure to clean up bone spurs on my right hip and (we hope) a little tidying of the labrum.

The weirdest thing is I don't know how I did it. A few years ago, we owned a house on an acre-sized lot, and toward the end of push-mowing sessions, that hip seemed to become really tired. The worst incident was after—not during!—a street hockey game where I suddenly couldn't walk and had to use my stick as a cane. You'd think there'd be some nasty collision or fall or something to pin this on, but it really seemed to come out of the blue.

That's been a couple of years ago. Back then, I didn't know I had a likely tear and hoped that I could work through the condition. In my defense, the pain was only in certain positions, and I walk limp-free. Deep squats at the gym hurt, and I hope I didn't do additional damage trying to tough it out.

So I'm facing four to six weeks on crutches and several months of rehab. It's tough getting old.

Monday, June 08, 2009

No legal plunder

In The Law, Frédéric Bastiat argues that a lack of what he derisively refers to as legal plunder is “the principle of justice, peace, order, stability, harmony, and logic.”

Although it was written more than a century and a half ago, Bastiat's frank criticisms have held their edge, but public ministers continue making the same mistakes he so harshly condemns. Consider the section called The Proper Function of the Law:

And, in all sincerity, can anything more than the absence of plunder be required of the law? Can the law — which necessarily requires the use of force — rationally be used for anything except protecting the rights of everyone?
Note that Bastiat uses “rights” in the same sense as Jefferson and Locke did, under which all are equal and must abide within the limits of this universal equality. Some characterize the concept as “negative rights,” e.g. no one may steal from, defraud, or murder others. Columnist Charley Reese put it in downhome terms: “The best way to understand the difference between a true right and a falsely claimed right is that a true right does not compel anyone else to do anything except leave us alone.”

Although not at all glamorous, Bastiat asserts (and later supports) that protecting these rights is a big enough problem for the law. He uses the rhetorical question to assert that broadening the scope of the law beyond this essential function is irrational.

I defy anyone to extend it beyond this purpose without perverting it and, consequently, turning might against right. This is the most fatal and most illogical social perversion that can possibly be imagined.
As experience and history show plainly, placing great power in the hands of a few rulers creates a vicious struggle to control its reigns. The concern moves from seeing that right prevails to becoming the mighty. During the Bush years, Democrats wailed about the abominable “Patriot” act and how it was forced upon them, but they then nominated for vice-president a man who claimed to be its intellectual forebear. Now that they control the White House and the congress, the alleged party of the common man has failed through inaction as terribly as the alleged party of small government that levied this surveillance-state measure.
It must be admitted that the true solution — so long searched for in the area of social relationships — is contained in these simple words: Law is organized justice.
Although anathema to the wonks and their grand schemes, they need to first master their humble assignment before pursuing more ambitious goals. Bastiat continues concerning justice:
Now this must be said: When justice is organized by law — that is, by force — this excludes the idea of using law (force) to organize any human activity whatever, whether it be labor, charity, agriculture, commerce, industry, education, art, or religion. The organizing by law of any one of these would inevitably destroy the essential organization — justice. For truly, how can we imagine force being used against the liberty of citizens without it also being used against justice, and thus acting against its proper purpose?
Consider the horrid mess of the Wall Street bailouts. Diane Feinstein openly admitted constituents' opposition was better than 9-1, but this “representative” voted for it anyway. The U.S. auto industry is a complete trainwreck, but Washington is forcing Americans to continue propping it up despite years of bailouts in the form of protective tariffs. Californians overwhelmingly rejected proposals for huge tax hikes, and now with the prospect of a federal bailout for Arnold & Co. (rivers of paper money flowing into the Golden State!), the people are likely to be forced to pay up even though the vox populi spoke an unmistakable No!

Unjust measures all! Each one is legal plunder. Carry the economist's old saw “there ain't no such thing as a free lunch” a step further: who must pay, and is it justice or might-cum-right?

Sunday, June 07, 2009

GWT not hitting breakpoints in hosted mode

With Eclipse 3.4.2 (Ganymede), Google Web Toolkit, and JDK 1.6.0_14, the debugger seemed to ignore my breakpoints while running the hosted-mode browser even though the breakpoint indicators had checkmarks while the app was running. I added calls to GWT.log, and the server's log output demonstrated that control was definitely passing through my breakpoints.

Google's Rajeev Dayal confirms the problem, and Eclipse has a ticket associated with this issue.

One workaround is falling back to JDK 1.6.0_13. If you don't have it yet, download it from Sun, and tell Eclipse about it:

  1. In Eclipse select Window > Preferences.
  2. In the Preferences dialog, select Java > Installed JREs.
  3. In the Installed JREs panel, select the Add... button.
  4. In the Add JRE dialog, select Standard VM and then the Next button.
  5. Select the Directory... button next to the textbox labeled JRE home and navigate to the JRE bundled with JDK 1.6.0_13 (e.g., C:\Program Files\Java\jdk1.6.0_13\jre). This should add several JARs to the list of JRE system libraries.
  6. Select the Finish button.
  7. Back in the Installed JREs panel, check the JRE for update 13, and then click
Set breakpoints, launch the debugger, and your application should now be stopping when control reaches the specified lines of code!

UPDATE: early-access release 6u18 is reported to fix this problem.

Saturday, June 06, 2009

Quidquid latine dictum sit, altum videtur

Sally suggested the title quote has a dynamic equivalent in C “and could be even more obfuscated!”

What do you think?

#include <stdio.h>
char s[]=" iptanohs iosonwa' nltnsud \
rfud";int i=sizeof s;void p(int n){n<i
<<1):3;}int main(){p(0);putchar('\n');}

Loading object files into ghci

On Haskell-Cafe, Murray asked about loading objects associated with FFI imports in ghci.

FFI is Haskell's Foreign Function Interface and allows interoperability with other languages, e.g., calling into a C library from Haskell or using your Haskell module from a C program. For more examples, see the FFI cookbook.

GHC's interactive environment, invoked with ghci, evaluates Haskell code in a REPL, loads and runs compiled modules, and provides familiar debugger functionality such as stepping, tracing, and catching exceptions.

Consider the following simple Haskell program that comprises two modules: Even though our program is split into multiple modules, we need point ghci at the main module, and it will follow the other dependencies:

$ ghci hello.hs 
GHCi, version 6.10.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
[1 of 2] Compiling Message          ( Message.hs, interpreted )
[2 of 2] Compiling Main             ( hello.hs, interpreted )
Ok, modules loaded: Main, Message.
*Main> main
Hello, world!
(If you're invoking ghci from Cygwin, you'll want to use ghcii.sh.)

With FFI, you have to hold ghci's hand a little. Consider the following shell script: The environment variable PREFIX is the path to the parent of the lib directory where your library lives. In my case, I ran ./configure --prefix=$PREFIX to ultimately install mylib in a non-standard location.

We might look for a directory named dist if building with Cabal.

The FFI gateway between my Haskell code and my C library is in a file named mylib.hs and compiles to mylib.o, whose path ghci needs to know in order to load all dependencies.

Finally, we invoke ghci. This particular program used hxt, the Haskell XML Toolbox, and mylib links against HDF5, the expat XML parser, and the single-precision FFTW.

For projects built with Cabal, the build system already knows all this information. With cabal-install, it's already possible to configure, build, test, and install Haskell packages. It'd be sweet to be able to easily load complex packages in ghci instead of having to resort to such hackery!

Friday, June 05, 2009

Waiting for Go-done

A coworker called this morning wanting to know how to get a list of files that do not contain the text 'Program complete' on any line. They run jobs in big batches, and each process writes its output to a separate file. The running times vary, and they wanted an easy way to see at a glance which processes are still running.

Running grep -v will print all lines that don't match the given pattern, but that doesn't help in this case because we want to treat the output files as though each contained a single line.

With the -c option, grep outputs the number of lines that matched. Say we have outputs named output1 through output4, and the odd-numbered jobs are finished. This would give us

$ grep -c 'Program complete' output*
The pattern requires quotes because it contains a space. Without the quotes, grep would search for Program in files named complete, output1, and so on.

The outputs for the processes still running are the ones containing zero matches, so let's look for those:

$ grep -c 'Program complete' output* | grep ':0$'
Remember that a dollar sign in a regular expression anchors the match to the end.

Quick cleanup with sed gives us the names of the outputs (backslash is the shell's line-continuation marker that lets us split long lines):

$ grep -c 'Program complete' output* | \
  grep ':0$' | \
  sed -e 's/:0$//'

UPDATE: Turns out there's a much easier way to do it. GNU grep has a --files-without-match option (aka -L), so the command is the simple

$ grep -L 'Program complete' output*

Thursday, June 04, 2009

Dear Congressman Griffith

Before entering office, you gave your solemn word to support the U.S. constitution. Article I, Section 8 of that instrument invests in the Congress oversight of the currency of the United States: “The Congress shall have power to … coin money, regulate the value thereof, and of foreign coin …”

As an aside, the English verb coin has a couple of meanings. One is to stamp metal with guarantees of weight and fineness. The other is to invent out of thin air, as in “coin a phrase.” The delegates in Philadelphia clearly intended the first sense, but others have substituted the latter via stealthy amendments.

I write to urge you to join with 186 (as of this writing) of your colleagues in the people's House and cosponsor HR 1207, the Federal Reserve Transparency Act.

In earlier correspondence, you passed the buck to the Financial Services Committee, writing that you will keep my views in mind "should this legislation reach the House floor for a vote." More than forty percent of your fellows have forsaken the slick politician's fence-sitting, non-committal, wait-and-see opportunism in favor of leadership by taking clear stands.

In the same letter, you assured me that you “support the highest level of accountability.” HR 1207's sunshine on the Federal Reserve, a body that acts in your name thanks to the oath of office you took willingly, would create accountability where secrecy and subterfuge have been the standard, and your active support would demonstrate your commitment to open, honest, accountable government.

Sincerely yours,
Greg Bacon

UPDATE: Mr. Griffith has cosponsored HR 1207!