Drastic Prelude changes imminent

Herbert Valerio Riedel hvr at gnu.org
Sun Feb 1 12:09:02 UTC 2015


Johan,

On 2015-01-31 at 18:59:31 +0100, Johan Tibell wrote:
> [...] Alternatively I can write
>
>     import qualified Data.Foldable as F
>
> but now nothing is gained over the pre-FTP state. Only after 3+ years
> (at the current GHC release phase) I can drop that one extra
> import.

Fwiw, the 3+ year argument applies to almost any `base`-augmentation if
you need such backward-compatibility. By that argument there's little
incentive to add anything to `base` at all.

> One out of perhaps 20. That seems quite a small gain given that we
> will then have made Data.List a very confusing module (it's
> essentially Data.Foldable under a different name), broken some code
> due to added type ambiguity,

So pre-FTP (in GHC 7.8), the following is needed to more or less emulate
the post-FTP state:

  import Data.List hiding (foldl',foldr,mapAccumL,mapAccumR,all,any,and
                          ,concat,concatMap,elem,find,foldl,maximum,foldl1
                          ,foldr1,maximumBy,minimumBy,product,notElem,sum,or
                          ,minimum)
  import Control.Monad hiding (forM,forM_,mapM,mapM_,sequence,sequence_,msum)
  import Prelude hiding (mapM,mapM_,sequence,sequence_,forM,foldr,foldl,foldl1
                        ,foldr1,elem,maximum,all,any,and,concat,concatMap
                        ,notElem,or,sum,product,minimum)
  import Data.Foldable
  import Data.Traversable

Notice all the tedious hiding-clauses you need (which differ slightly,
depending on which subset of the 4 modules you want to import -- is
there even any editor/tool that helps to auto-generate those 'hiding'
imports?) in order to avoid any conflicts. This makes (at least me)
think twice before making use of Foldable/Traversable, which in turns
hinders the wider adoption of Foldable/Traversable, which then leads to
proposals of adding redundant combinators such as `whenJust`, when we
already have `forM` for that, but which in turn lives in a module which
requires a bit of ceremony to use, so users instead resort to locally
define `whenJust` over and over again against the DRY principle. If we
don't intend to make Foldable/Traversable a first-class citizen of
Haskell to help increase its adoption, why have it in `base` in the
first place?

Moreover, how do we justify (other than by historic accident) that the
more generalised synonyms are stored away in modules for which the
current recommendation is to use qualified imports, while the
list-specialised versions are in scope default, while other
data-structures (Data.Map, Data.Sequence, Data.Set, ...) require to use
qualified imports again? Do lists really require such a special
privilege?

Why not rather place the more general versions into the default scope,
and require the list-specialised versions to be qualified-imported (for
the few cases you need those) instead? This results in a more symmetric
situation.

> and also removed one of the simpler ways to remove that ambiguity,
> which would have been to import one of the monomorphic list functions
> that no longer exist.

Fwiw, there are a few ideas being considered to address this by bringing
back access to the list-specialised versions (e.g. something like
'Data.List.Mono' modulo-naming, or by implementing weak/shadowing import
support, maybe in combination with re-export deprecation to help migrate
to qualified Data.List-imports)

The design-choices of the FTP implementation were motivated to achieve
its goal while breaking as little existing code as possible. We assumed
this to be the better compromise rather than introducing a severe
breakage of the majority existing Haskell code which don't
qualify-import `Data.List`.

Cheers,
  hvr


More information about the Libraries mailing list