On Fri, Dec 27, 2013 at 4:11 PM, Ben Millwood <haskell@benmachine.co.uk> wrote:
On Sun, Dec 22, 2013 at 12:02:16PM -0800, John Lato wrote:
On Dec 22, 2013 7:28 AM, "Herbert Valerio Riedel" <hvr@gnu.org> wrote:

On 2013-12-22 at 11:32:20 +0100, Thomas Schilling wrote:
> Either I should be able to check at compile time, or I should get a
> defined exception call which then must be handled by the library.  In
> either case it should be documented with the function.

It might be worth adding more information to the Haddock-comments
mentioning the respective `HAVE_*` CPP symbol and whether a
fallback-implementation is used.

Moreover, the use of `error` to signal non-existing implementations
could be reconsidered (e.g. maybe switch to a properly thrown
"call-not-implemented" exception)

This would definitely be better than calling error. Personally I would
prefer conditional exports, as it would turn up errors sooner.

John L.

What does client code look like, if this is your implementation strategy? Note that the network package recently changed to *stop* conditionally exporting things, because it led to bad error messages (yes, your error is caught at compile time, but it's not so clear what it *is*) and ugly client code. See e.g. https://github.com/haskell/network/issues/40

These days I pretty much exclusively work on linux systems, so my client code is pretty clean :)

I would consider that example from the network package a different situation.  Conditionally-defined data types are not the same as a function that might not be exported.  If you're serializing/logging, it makes perfect sense to enumerate values that aren't supported locally for example, and I can see that working around that could lead to really ugly client code.  But I don't think it makes much sense to export a function that just calls error if it's unsupported.  Handling an exception is at least as awkward as CPP in that case, and in practice worse because we can't differentiate between error calls except by matching on the message string.  At least a custom exception would solve that problem.  But for me, conditional exports are still better.  A big advantage for us is that when we update our toolchain (e.g. a new ghc release comes out), it's much faster to find problems in the toolchain build by just typechecking code rather than actually needing to run executables to test every possibly-defined function we might call (of course we do end-to-end testing as well, but this is a case where errors arising sooner leads to significantly less work).

As an alternative, how about throwing an exception, but also using CPP to add a WARNING pragma to any function that's system-unavailable?  Then we'd get a good message at compile-time.

John L.