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

Herbert Valerio Riedel hvr at gnu.org
Sun Nov 11 22:06:42 CET 2012


Henning Thielemann <lemming at henning-thielemann.de> writes:
> 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.

 a) If you are allowed to forget to implement 'size', then your type was
    able to provide a 'Generic' instance, how was that instance possible
    to come into existence in the first place?

 b) what if GHC provided something akin to a
    -fwarn-instantiate-default-signatures GHC option, which might even
    be turned on by default?

 c) what if GHC behaved like outlined in
    http://hackage.haskell.org/trac/ghc/ticket/7395#comment:7 instead?

> 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?

Fair enough, but breakage with newer GHCs can also happen when staying
in the pure Haskell98/2010 domain (just think of the Num/Show/Eq
superclass decoupling that occured in recent GHC versions). That is, for
Haskell libraries there's always the risk needing maintainance when a
new GHC version comes out. (But I'm not arguing this to be a good thing
either...)

> 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?

Are you preferring 'genericSize' to avoid the implicity that comes with
DefaultSignatures, and the resulting risk of inadvertently writing
non-portable code because GHC currently doesn't warn you?




More information about the Libraries mailing list