Deprecate Foldable for Either
Edward Kmett
ekmett at gmail.com
Mon Mar 20 03:41:12 UTC 2017
On Sun, Mar 19, 2017 at 9:33 PM, Adam Bergmark <adam at bergmark.nl> wrote:
> Ed, If i understand you correctly then this poisoning doesn't scale. If I
> want to use it in my library I'm also forcing all my users to avoid these
> functions and it would split hackage in half. Effectively I'd only be able
> to use it for private code and applications. Or am I misunderstanding?
>
This is why I mentioned at the end that if you're doing this for a library
you probably only want to enable poisoning with a cabal build flag. That
way you can use it to verify that you build clean even with the poison
enabled without crippling your users. Think of it like -Werror. You don't
ship cabal packages with it enabled but you often use it locally. For
classroom teaching scenarios using a custom prelude that poisons things
fits the bill. If you are concerned about certain instances leaking into
your private code, you can also poison willy-nilly, and nobody needs care.
If you poison behind a flag it doesn't leak out into the ecosystem, and if
you choose not to poison behind a flag, then people can choose to accept or
reject your poisoned instances on their own merits.
e.g. async had an instance of Monad for Concurrently that was incompatible
with its Applicative until recently. Fortunately, Simon Marlow was willing
to listen to reason. However, had he not been, it is a situation where I
could bring myself to resort to poison. Er... that sounds rather more
gruesome than intended. Sorry, Simon. :)
You can already do this in poisoning in a solid way by defining e.g. `class
> Unsatisfiable; instance Unsatisfiable => Show (a -> b) where show =
> undefined` and not exporting Unsatisfiable.
>
Yes, if you want to ensure that an instance is never defined, but that
doesn't work for things where there is already an instance in scope. You
can't retroactively poison Foldable ((,) e) with this technique, as the
class and instance are defined together in the same module (or the data
type and instance are), as they have to be to avoid orphans, and so you
never get a chance to interject a conflicting poisonous instance without
GHC telling you that your instance collides with the existing instance as
an error.
-Edward
Cheers,
> Adam
>
>
>
> On Mon, 20 Mar 2017 at 01:56 <amindfv at gmail.com> wrote:
>
>> Edward: this is clever! I can't at the moment see any reason this
>> wouldn't work for all parties: those who want the instances can have them,
>> those who don't can "turn them off," and beginners can start with a prelude
>> that turns them off also.
>>
>> We will need to be clear about which packages (transitively) poison
>> instances.
>>
>> Tom
>>
>>
>> El 19 mar 2017, a las 19:21, Edward Kmett <ekmett at gmail.com> escribió:
>>
>> Sadly, hlint remains fairly (er.. completely?) ignorant of the types of
>> an expression. It has no idea what is in scope, and just provides
>> syntax-directed guidance, so hlint isn't the answer here.
>>
>> That said, there does seem to be a plausible solution available.
>>
>> I have zero objection to adding {-# POISON #-} pragma that users could
>> include in their own code that just makes it so that whatever instance is
>> named inside of it becomes unusable. You could view it as setting up an
>> ambiguous instance declaration that is currently impossible to write, so
>> any attempt to use the instance would complain about ambiguous instances
>> (or preferably about the instance being poisoned and name the source of the
>> poison).
>>
>> This would make the status quo the norm, but then you could modify your
>> custom Prelude or what have you to {-# POISON instance Foldable ((,) e) #-}
>> and then any code that transitively depended on your Prelude would complain
>> if it attempted to use that instance.
>>
>> Such a poison pragma should be sound with respect to GHC's internals. It
>> is effectively making an extra instance just to cause conflicts later on in
>> the instance selection process. This is the same as if we had Foldable the
>> class being defined in one module, the real instance in another, someone's
>> poison instance in a third, then a fourth module that imports the whole
>> diamond. Any attempt to use the instance that is defined in two
>> contradictory ways in that 4th module today will complain.
>>
>> Folks who care about these instances would then have the choice about
>> whether to avoid any package that poisoned any instances they cared about,
>> and folks who fee strongly about this issue would be able to live in a
>> world where these instances didn't affect any code they wrote and if they
>> didn't want to turn off users that care about being poisoned, could turn on
>> the poisoning through cabal flags so that they don't infect their API but
>> get an opt-in internal consistency check for local compilation.
>>
>> -Edward Kmett
>>
>> P.S. The term poison above derives from the C convention of poisoning
>> names you don't want to see in your code due to safety considerations. e.g.
>> In GCC you can do so with
>>
>> #pragma GCC poison printf sprintf fprintf
>>
>>
>> On Sat, Mar 18, 2017 at 8:51 PM, <amindfv at gmail.com> wrote:
>>
>>
>>
>> > El 18 mar 2017, a las 16:01, Lana Black <lanablack at amok.cc> escribió:
>> >
>> >> On 18/03/17 19:49, Henning Thielemann wrote:
>> >>
>> >>> On Sat, 18 Mar 2017, Carter Schonwald wrote:
>> >>>
>> >>> for what?
>> >>
>> >> A warning if someone e.g. calls 'length (a,b)', or more generally, if
>> >> certain instances are used.
>> >> _______________________________________________
>> >> Libraries mailing list
>> >> Libraries at haskell.org
>> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>> >
>> > Please no. Many of us like our code Wall-clean while still being able to
>> > write polymorphic functions. Adding more warnings that are often
>> > triggered by correct code (redundant constraints, anyone?) only leads to
>> > more headache.
>> >
>> > You could make that an hlint rule on the other hand.
>>
>> Can it be a hlint rule? It seems quite difficult to predict that "length"
>> will not ever be passed e.g. a 2-tuple in the general case, within hlint.
>>
>> I would also favor a warning, and happily have -Wall not include it
>> (though I'd prefer inclusion).
>>
>> Tom
>>
>>
>> > _______________________________________________
>> > Libraries mailing list
>> > Libraries at haskell.org
>> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>> _______________________________________________
>> Libraries mailing list
>> Libraries at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>
>>
>> _______________________________________________
>> Libraries mailing list
>> Libraries at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20170319/c9064255/attachment.html>
More information about the Libraries
mailing list