Unavailable system functions in `unix` (was: Pull request for inclusion in `unix' module of fsync(2), fdatasync(2), posix_fadvise(2) and posix_fallocate(2))

John Lato jwlato at gmail.com
Sat Dec 28 19:24:37 UTC 2013

On Fri, Dec 27, 2013 at 4:11 PM, Ben Millwood <haskell at 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 at 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/libraries/attachments/20131228/b8c71c69/attachment.html>

More information about the Libraries mailing list