RFC: Can DefaultSignature compile-time conditional APIs be regarded "benign"?
Henning Thielemann
lemming at henning-thielemann.de
Sun Nov 11 21:21:51 CET 2012
On Sun, 11 Nov 2012, Herbert Valerio Riedel wrote:
> 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)
That is, if I want to write a package that is portable I have to implement
'size' myself. But if I forget to do so then GHC will not warn me. That
is, I have to know and remember that 'size' is somehow special.
APIs that change according to available compiler features are more
problematic than they look first. E.g. QuickCheck depends on
TemplateHaskell if you run on GHC. That is, if you run on GHC then a
module is included that provides TemplateHaskell functions. If you do not
run on GHC this module is not included because you cannot use it anyway.
However, this way QuickCheck becomes restricted to certain _versions_ of
GHC, because TemplateHaskell changes from version to version of GHC. Thus
when speaking about portability, we should always think about portability
between GHC versions. (My proposal for a quote of the week is: GHC's
strongest competitor is the next version of GHC.) Will the Generics based
default implementation of 'size' be portable to future version of
Generics?
For a central package like deepseq I would prefer to provide functions
like genericSize that other libraries can use if they want to rely on
Generics. They would then write
instance Size Foo where
size = genericSize
instead of
instance Size Foo where
This would be ok, wouldn't it?
More information about the Libraries
mailing list