[Haskell-cafe] Unexported functions are evil

ajb at spamcop.net ajb at spamcop.net
Sun May 15 21:42:22 EDT 2005


G'day all.

Quoting Peter Simons <simons at cryp.to>:

> I was wondering: Is there any reason why you would have a
> function in one of your modules and _not_ export it?

The short answer: Because that function is nobody else's business.

The long answer:

The reason why programming is hard is that programs are complex.  The art
of software design and construction is the art of controlling that
complexity so that it doesn't get out of hand.

Paraphrasing what David Roundy said, every piece of code (with the
possible exception of main) that you write is an API for some other
part.  Controlling the complexity means that

> I ask because I have _never_ had problems with a module
> exporting too much, but I have had problems with modules
> exporting too little quite frequently.

Continuing on from the previous thought, part of the problem here is that
we teach people to write code (e.g. how to implement a sort), but we don't
teach people to write APIs.  APIs are both trickier to get right AND are
more important in larger programs.

So while I think you've identified a real problem (the modules that you
want to use expose insufficient APIs), I think your solution is wrong.  The
right solution is to complain to the module writer, and ask them to export a
functionally complete API.

> The reason why I like purely functional languages like
> Haskell is that it is virtually impossible to write code
> that cannot be reused.

I'd disagree with that.  Strongly.  Very strongly.

It's _easier_ to write reusable code, for sure.  But reusable code is
tricky no matter what you do.  And according to Alan Perlis, you never
know if it's truly reusable until you've reused it at least three times.

> The only reason I could think of is that a function is
> considered to be "internal", meaning: You don't want users
> of the module to rely on the function still being there (or
> still working the same way) in any of the next revisions.

Right.  And I agree with David: This is reason enough.

With my business hat on: Every time you expose something for use, you must
at the very least document it.  At most, you are implicitly supporting it.
If you have customers that have spent money or other resources on your code,
then you owe it to them.

> On those occasions, however, why not put the function into a
> module, say "Foo.Bar.Private" and import it into "Foo.Bar"
> from there? Then those people who enjoy playing with fire
> _can_ use it, and everybody else will not.

Taking this to an illogcial extreme, why don't we allow pointer arithmetic
in Haskell, but require people to import "Prelude.C" first, so that people
who enjoy playing with fire can do it?  After all, we use it under the
covers...

Cheers,
Andrew Bromage


More information about the Haskell-Cafe mailing list