Hi everyone, and happy holidays.
I am looking into whether or not Safe Haskell is still worth maintaining.
Currently there are two sides on which Safe Haskell hurts us:
- GHC Development
- Library development
For point n°1: You can easily take the measure of what Safe Haskell raises in GHC as of today by visiting the bug tracker¹ and see that for example Unboxed Types cannot be used because their home modules (GHC.Prim and GHC.Types) are marked as Unsafe. Moreover, interactions between GHC2021 and Safe make the latter quite unpleasant to work with².
Regarding point n°2: Safe Haskell is badly integrated within our existing frameworks for API compatibility. Neither the PVP nor the extension’s documentation mention compatibility, or define what stance we should take. Thus we are bound to fight on the letter versus the spirit of the PVP (which is not an unreasonable debate since there is no formalism anywhere). This provokes debates without clear resolution beyond "Friend don’t let friends use {-# Safe #-}
"³
Now I am not saying that Safe Haskell does not bring any kind of good idea, far from it.
However there are two things that live inside Safe Haskell that would benefit from being separated:
-
Strict type-safety
-
Restricted IO
A lot of the public use-cases of Safe Haskell seem to be on the “Restricted IO”, such as Lambdabot and other code evaluators out there.
It’s a fairly reasonable feature, I’d even say it’s something that we should be publicising more when speaking about GHC’s more advanced features. However, “Strict type-safety” seems to be the root of many problems that we encounter downstream. A lot of it stems from GeneralizedNewtypeDeriving being marked as unsafe (under point 1), which is fair enough, but we’ve had DerivingVia not marked as Safe until May 2021, which reveals a big problem: Options have to be marked as forbidden under Safe to be caught, which leaves a lot of work to the human factor of GHC development.
Now, there are two options (convenient!) that are left to us:
-
Deprecate Safe Haskell: We remove the Safe mechanism as it exists today, and keep the IO restriction under another name. This will certainly cause much joy amongst maintainers and GHC developers alike. The downside is that we don’t have a mechanism to enforce “Strict type-safety” anymore.
-
We heavily invest in Safe Haskell: This is the option where we amend the PVP to take changes of Safety annotations into account, invest in workforce to fix the bugs on the GHC side. Which means we also invest in the tools that check for PVP compatibility to check for Safety. This is not the matter of a GSoC, or a 2-days hackathon, and I would certainly have remorse sending students to the salt mines like that.
I do not list the Status Quo as an option because it is terrible and has led us to regularly have complaints from both GHC & Ecosystem libraries maintainers. There can be no half-measures that they usually tend to make us slide back into the status quo.
I have probably missed crucial elements in my post, please feel free to add information or correct me.
So, what do you think?