[Haskell-cafe] Deprecation being transitively reported for re-exported definitions

Oleg Grenrus oleg.grenrus at iki.fi
Sun Aug 15 02:52:47 UTC 2021

I think the confusion stems from what the deprecation of the module
means, i.e.

    module A {-# DEPRECATED "This module will be hidden in future
versions". #-} ( ... ) where

I think it does two things:

1. deprecates the module A, so if it's  imported anywhere, the
deprecation warning will be reported
2. deprecates all symbols defined in the module, so the use-sites are
reported as well. (This is like deprecating an individual binding, {-#
DEPRECATED symbolInA "..." #-}.

The second point is why re-exporting names defined in A still causes the
warning. The thing is deprecated, it doesn't matter how you import it.
However, if A re-exports some other symbols (e.g. from A.Internal),
these things are not deprecated, and thus no warnings.

This explains why a workaround you mention works. Or we could even argue
that the (first) workaround is not even a workaround, but the right way
to do what you want.

Defining new binding is not the same as re-exporting. There is a bit
discussion about it in [1], e.g. users can define different RULES for
the thing "renamed" in B.

There is an interesting challenge in [1] too:

>  the proposal would be stronger if it explicitly explained that much
of what is proposed [renaming on import] could be done with existing
mechanisms [like writing new definitions, type, etc.]

For your use case (in second workaround) you'll rely that redefinition
(as "heavy" renaming) will strip the deprecation bit. But we can argue
that it's still a renaming, so it should not! :)


- Oleg

On 15.8.2021 4.22, Ivan Perez wrote:
> Hello Café,
> TL;DR: should the deprecation GHC option be transitively reported for
> re-exported definitions?
> I have a library that is exposing too much. As a minimal example, say
> the library contains:
> - Module A, which defines several functions and types.
> - Module B, which exports /specific definitions/ from module A and has
> none of its own.
> It so happens that, to keep things as clean and abstract as possible,
> only module B should be exposed.
> As per library policy, we give users time to adapt. A way to do that
> would be to deprecate module A, but configure B to ignore deprecations
> (-Wno-deprecations) so GHC does not complain during the compilation of
> the library itself.
> My expectation was that library users who imported /A directly/ would
> get a warning, but importing definitions in A /via B/ would not give
> out any warnings.
> That, however, is not what is happening:
> In the use of ‘functionInA’
>     (imported from B, but defined in A):
>     Deprecated: "This module will be hidden in future versions."
> There are "workarounds": I could move all definitions in A to new
> module C, deprecate A, and re-export C in B, or I could re-define the
> exported definitions in B as identities of those in A (easy for
> functions, probably more cumbersome for data constructors or classes.)
> However, more generally, if you use a function from A in a NEW
> function definition in B and then export /that second definition
> instead/, the compiler won't tell /the library user/ that B is
> internally relying on a deprecated function. Reexporting a function
> without changes could conceptually be seen as an "extreme" case of
> that, where where the name and the implementation in B coincide with
> those in A.
> So I ask: should deprecation work the way it is working in the first
> place?
> All the best,
> Ivan
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20210815/cdaf4764/attachment.html>

More information about the Haskell-Cafe mailing list