RFC: Can DefaultSignature compile-time conditional APIs be regarded "benign"?

Herbert Valerio Riedel hvr at gnu.org
Sun Nov 11 15:34:55 CET 2012


Dear List,

After recent discussions[1][2], from which I gathered that
(compile-time) conditional APIs should be avoided, I'm left wondering if
a certain kind of compile-time conditional API falls into that category
as well, or whether it can be classified as "benign" and should
therefore be tolerated.

So I'm posting this for open discussion in the hope to reach a community
consensus on whether the conditional use of the "DefaultSignature"
language extension in APIs should be tolerated or not (e.g. for
haskell-platform packages). To this end, in the rest of this post I try
to make a case for why this class of conditional APIs is harmless.

-----

So what's bad about "conditional" APIs? The way I understand the issue
with respect to compile-time conditional APIs which either

 a) omit exposed modules or exported symbols altogether based on
    compile-time configuration, or even worse

 b) export different type-signatures for the very same symbol based on
    compile-time configuration

are "bad", as they cause problems in client code using those APIs, such
as

 a) not being able to properly declare the dependency on specific API
    features being enabled in the library API in CABAL files (since
    CABAL only allows to depend package version numbers),

 b) and from the other direction, there's no simple way for the library
    package to advertise the conditional features currently present in
    the registered package.

 c) Moreover, if the client code wants to use symbols which depend on
    compile-time configuration, it either becomes non-portable and/or
    becomes compile-time conditional itself.

    Note: It should be stressed that in the latter case the client code
    needs to take care to *exactly* replicate the semantics of the
    conditional switching between the API variants as employed by the
    library code (which can be CPP-based and/or CABAL-based), as any
    mismatch may result in compile time failures. This also poses the
    issue on how to properly document this "meta-property" in the
    library API documentation.

(there may be more reasons, I just listed the ones off the top of my head)


On the other hand, I think that there are cases, when a compile-time
conditional API is "benign", for instance when the following condition
holds:

 a) the library package exposes a /non-essential/ API feature based only
    on availability of a given compiler-feature/extension, 

 b) the conditional feature is only ever visible to the client code if
    the client makes use of this compiler-feature itself, and last but
    not least

 c) the semantics of the client code must not change if the client code
    has been made portable (with respect to the availability of the
    conditional feature)


E.g. consider the following hypothetical class definition:

	class Size a where
	  size :: a -> Int
	#ifdef HAS_DEFAULT_SIGNATURE
	  default size :: Generic a => a -> Int
      size x = ...Generics based implementation...
	#endif

Now, if the client code doesn't exploit the default-signature
implementation, then the client code is perfectly portable, and even if
the conditional API features are available they have no visible effect
whatsoever.

OTOH, if the client code wants to make use of the default
implementation, it needs to be built with a compiler supporting the
Generics language feature, and due to a) the library is guaranteed to
provide the default-signature implementation as well as soon as the
client is able to use it. The client-code is now deliberately
non-portable (but on the other hand, the operational semantics are
guaranteed to be consistent, as there's only one case to consider)

Consequently, as both scenarios don't lead to problematic situations,
I'd argue that there is no harm in allowing this kind of compile-time
conditional APIs using the DefaultSignature language extension.

----

cheers,
hvr

 [1]: "Proposal: Adding generics-based rnf-helper to `deepseq`"
      on libraries list
      http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17940

 [2]: "[ANNOUNCE] hashable-generics"
      on haskell-cafe list
      http://comments.gmane.org/gmane.comp.lang.haskell.cafe/101323



More information about the Libraries mailing list