Hi Johan,
Thanks for replying. I think there are one or two slight misconceptions
about Safe Haskell - that's understandable, I think the documentation
could be improved, and the paper that explains it properly isn't
available yet (we only just finished the camera-ready copy, so it'll be
available soon).
Anyway, let me try to explain. It's not nearly as bad or onerous as you
think.
Safe Haskell isn't about catching bugs. It's about making it possible
to program with stronger guarantees than we currently have. The problem
is that Haskell provides a bunch of loopholes by which you can violate
things like type-safety and referential transparency, and the purpose of
Safe Haskell is to make it possible for GHC to check that you aren't
using any unsafe features, so your code is guaranteed type-safe and
referentially transparent.
Myth #1 seems to be that Safe Haskell excludes large amounts of Haskell
code that people want to write. Not at all! Normally when you use an
unsafe feature, the purpose is to use it to implement a safe API - if
that's the case, all you have to do is add Trustworthy to your language
pragma, and the API is available to use from Safe code. 99% of Hackage
should be either Safe or Trustworthy. We know that 27% is already
inferred Safe (see the paper), and a lot of the rest is just waiting for
other libraries to add Trustworthy where necessary.
The 1% is code that really exports unsafe APIs, like vector. These are
in the minority - ask yourself how many packages that you maintain
contain an unsafe API (zero, I think). Furthermore, even if there's an
unsafe API, so long as the unsafe API isn't part of the same module as a
safe API that you might want access to from Safe code, then you have
nothing to do - the API is just Unsafe.
For typical Haskell programmers, using {-# LANGUAGE Safe #-} will be
like -Wall: something that is considered good practice from a hygeine
point of view. If you don't *need* access to unsafe features, then it's
better to write in the safe subset, where you have stronger guarantees.
Just like -Wall, you get to choose whether to use {-# LANGUAGE Safe
#-} or not.
> We'd have to maintain a separate
> implementation of the UTF-8 decoder for use by SH users.
Not at all - we have one UTF-8 decoder, marked Trustworthy.
> If you want to write real code and use SH, you need to either avoid
> all these libraries or to trust (as in ghc-pkg trust) all these
> libraries.
No -the need to trust packages was turned off by default in 7.4.1, see
the -fpackage-trust flag.
> Despite none of them having had a thorough security review.
> In practice Trustworthy language pragmas on top of modules to make
> code compile. There are 139 modules in base marked as Trustworthy. I
> seriously doubt that they all are.
Whether you believe those claims or not is entirely up to you. Someone
who is relying on Haskell for security has to trust a lot of things -
GHC itself, the RTS, not to mention the hardware. Safe Haskell just
makes it a bit clearer what you have to trust, and allows GHC to
automate some of the checking.
> SH also prevents
> optimizations, like rewriting a particularly hot function in C, as it
> would change its type.
Again, the API would be Trustworthy.
> SH is much more invasive than your typical language extension. It
> requires maintainers of libraries who don't care about SH to change
> their APIs (!)
It will be very rare for this to happen. The vast majority of packages
do not expose unsafe APIs, so at most all that will be needed is some
Trustworthy pragmas, and in many cases no changes at all are needed. In
the very few cases where there is a mixed safe/unsafe API, and we really
care about Safe access to the safe parts, then the unsafe parts should
be moved into a .Unsafe module.
I don't think adding a few Trustworthy pragmas is very onerous, and
arguably it's good documentation anyway.
> just to support a yet unproven language extension. The
> reason is that SH is an all or nothing approach. Either all your
> dependencies are SH aware or your code won't compile. This is the
> opposite of how we handle any other language extensions, where people
> can slowly try out new language features in their own code and only
> have people who chose to use that code also have to use that feature
> e.g. if I use type families in a library that depends on containers,
> that doesn't imply that the containers package have to use type
> families. This is however true for SH.
Of course it's your prerogative as a library maintainer to decide
whether to use Trustworthy or not. For the platform I think the bar is
a little higher, and cleanly separating safe from unsafe APIs is warranted.
> If we start using TH in our core libraries we risk making those
> libraries more complicated for users to understand and use, without
> much perceivable benefit.
I don't think separating safe from unsafe APIs makes things more
complicated. We were doing that even before Safe Haskell - see e.g.
System.IO.Unsafe, and Unsafe.Coerce.
Cheers,
Simon