Saturday, September 18, 2010

Three Closed GHC Bugs I Wish Were Open

Summary: I want three changes to the Haskell standard libraries. System.Info.isWindows should be added, Control.Monad.concatMapM should be added, and Control.Concurrent.QSem should work with negative quantities.

Over the last few hours I've been going through my inbox, trying to deal with some of my older emails. In that process, I've had to admit defeat on three GHC bugs that I'd left in my inbox to come back to. All these bugs relate to changes to the Haskell standard libraries, that were opened as bugs, and that got resolved as closed/wontfix. I will never get time to tackle these bugs, but perhaps someone will? The bugs are:

Add System.Info.isWindows - bug 1590

module System.Info where

-- | Check if the operating system is a Windows derivative. Returns True on
-- all Windows systems (Win95, Win98 ... Vista, Win7), and False on all others
isWindows :: Bool
isWindows = os == "mingw"

Currently the recognised way to test at runtime if your application is being run on Windows is:

import System.Info

.... = os == "mingw"

This is wrong for many reasons:

  • The return result of os is not an operating system, but a ported toolchain.

  • The result "mingw" does not imply that MinGW is installed on the computer.

  • String comparisons are unsafe and unchecked, a simple typo breaks this code.

  • In GHC this comparison will take place at runtime, even though the result is a constant.

The Haskell abstractions and command line tools for almost all non-Windows operating systems have converged to the point where most programs with operating system specific behaviour have two cases - one for Windows and one for everything else. It makes sense to directly support what is probably the most common usage of the os function, and to encourage people away from the C preprocessor where possible.

Add Control.Monad.concatMapM - bug 2042

module Control.Monad where

-- | The 'concatMapM' function generalizes 'concatMap' to arbitrary monads.
concatMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]
concatMapM f xs = liftM concat (mapM f xs)

I've personally defined this function in binarydefer, catch, derive, hlint, hoogle, my website generator and yhc. There's even a copy in GHC. If a function has been defined identically that many times, it clear deserves to be in the standard library. We have mapM, filterM, zipWithM, but concatMapM is suspiciously absent.

Make Control.Concurrent.QSem work with negatives - bug 3159

The QSem module defines a quantity semaphore, where the quantity semaphores must be natural numbers. Attempts to construct semaphores with negative numbers raise an error. There is, however, a perfectly sensible and obvious interpretation if negative numbers are allowed. It is a shame that this module could provide total functions, which never raise an error, but does not. In addition, for some problems the use of negative quantity semaphores is more natural.

What Now?

I've removed all these bugs from my inbox, and invite someone else to take up the cause - I just don't have the time. Until these issues are resolved, I will test for Windows in a horrible way, define concatMapM whenever I start a new project, and lament the lack of generality in QSem. None of the issues is particularly serious, but all are slightly annoying.

Email etiquette: Today I've cleared about 50 emails from my inbox. Unfortunately my inbox remains big and unwieldy. If you ever email me, and I don't get back to you, email me again a week later. As long as you reply to the first message, Gmail will collapse the reply in to the original conversation, and there won't be any additional load on my inbox - it will just remind me that I should have dealt with your email. I apologise for any emails that have fallen through the cracks.