[Haskell-cafe] Best practices for modular programming in Haskell

Benjamin Pierce bcpierce at cis.upenn.edu
Wed Mar 16 22:25:56 EST 2005


For someone coming to Haskell from an OCaml background, one of the hardest
things to get used to is the somewhat more bare bones module system that
Haskell provides.  Naturally, as I've gotten into the Haskell groove I've
discovered (or learned from reading other people's code) nice ways of doing
*some* of the things that I was used to doing with OCaml modules, but there
are still things that I miss.  This leads me to wonder how expert Haskell
programmers address these issues.

For example, here's my biggest current puzzle: What is the best way to
expose the *interface* of a module (what would go in the .sig file in ML) to
programmers that need to know how to use it?

My impression is that there is no universally accepted "best way" to do
this.  Some people write their modules in the form:

   module Foo (<exported names>) where
   <type declarations for exported names>
   ------------------------------------------------------------- line of dashes
   <definitions of exported names (and other stuff)>

This works fine as long as what you're exporting is just values, but it's
awkward for types, since there is no way to *declare* a type (e.g., giving
just its kind) without *defining* it.  I suppose one could do something like

   module Foo (T,x) where
   type T = T_internal
   x :: T
   ------------------------------------------------------------- 
   type T_internal = Int
   x = 5

but it seems clunky.  

Other people seem to rely on Haddock to generate interfaces as
documentation.  This is nicer in many ways (e.g., it solves the above
problem because Haddock elides the right-hand side of a "data" or "newtype"
declaration if the constructors are not exported by the module), but it
means that you are stuck browsing interfaces in a web browser can't just
have a look with emacs.  This is especially annoying if you want to read the
interface in tandem with the implementation (because you are trying to
understand how the thing works internally but want to use the interface to
get a high-level picture of the functionality it presents to the world).

Are there other (perhaps better) ways that I'm not aware of?  

Thanks,

      Benjamin



More information about the Haskell-Cafe mailing list