[Haskell-cafe] where to put general-purpose utility functions

Joey Hess joey at kitenet.net
Sat Jan 21 21:20:25 CET 2012

I'm finding a rather unusual problem as I write haskell..

Unlike every other language I've used, large portions of my haskell code
are turning out to be general-purpose, reusable code. Fully 20% of the
haskell code I've written for git-annex is general purpose. Now, I came out
of a decade of perl with maybe 1% reusable code. So I'm sure this is a
credit to haskell, and not to me.

My problem now is that as I start new projects, I want to have my haskell
utility functions available, and copying them around is not ideal. So, put
them on hackage. But where, exactly? It already has several grab bag utility
libraries. The only one with much traction is MissingH. Using the others
makes a program have an unusual dependency, which while only a cabal
install away, would make work for distributions that want to package the
program. I've ruled out using a couple on that basis. Doesn't encourage me
to add another one.

My 2000+ lines of reusable code are a grab-bag of generic utility
functions. Looking them over (see Appendix), I could try to get portions
into existing libraries on hackage, but it's unlikely I'd find a home
for most of them, so I'm still left with this problem of what to do.

I wonder if the model used for xmonad-contrib, of a big library package,
that is very open to additions from contributors, would be helpful here?

John, any interest in moving MissingH in this direction? I get the
impression it's not otherwise changing much lately, and parts of it are
becoming naturally obsolete, maybe this could inject some life into it.
Any other thoughts you have on grab-bag utility libraries on hackage
also appreciated.


Appendix: A sample of a a few of the better functions from my utility library.

  Some quite generic monadic control functions, few of them truely unique:

  whenM :: Monad m => m Bool -> m () -> m ()   -- also >>?
  unlessM :: Monad m => m Bool -> m () -> m () -- also >>!
  firstM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
  A module that exports functions conflicting with partial
  functions in the Prelude, to avoid them being accidentially
  used. And provides some alternatives (which overlap somewhat with Safe):
  headMaybe :: [a] -> Maybe a
  readMaybe :: Read a => String -> Maybe a
  beginning :: [a] -> [a]

  Various path manipulation functions such as:
  dirContains :: FilePath -> FilePath -> Bool
  dotfile :: FilePath -> Bool
  absPath :: FilePath -> IO FilePath

  Other stuff:

  separate :: (a -> Bool) -> [a] -> ([a], [a])
  catchMaybeIO :: IO a -> IO (Maybe a)
  readSize :: [Unit] -> String -> Maybe ByteSize -- parses "100 kb" etc
  format :: Format -> Variables -> String
  findPubKeys :: String -> IO GpgKeyIds
  boolSystem :: FilePath -> [CommandParam] -> IO Bool
  withTempFile :: Template -> (FilePath -> Handle -> IO a) -> IO a

see shy jo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 828 bytes
Desc: Digital signature
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120121/c622e39f/attachment.pgp>

More information about the Haskell-Cafe mailing list