Version 10 (modified by igloo, 21 months ago) (diff)


Proposal: NoImplicitPreludeImport

Ticket #144
Dependencies (none)
Related #58, #124

Compiler support

GHC partial (-XImplicitPrelude) (conflates the import with overriding desugaring)
nhc98 unknown
Hugs unknown
UHC unknown
JHC unknown
LHC unknown


This proposal is to stop implicitly importing Prelude in Haskell modules.


The Prelude has been largely frozen since the 1990s or earlier, when Haskell was a much different language. For example, it exports sequence and sequence_ but not the more often used when and unless, which didn't exist in the days of Haskell 1.2 / GHC 0.29. Similarly, it exports scanl1, but not sort.

In other cases, such as mapM, the Prelude contains one version of a function whereas modern Haskellers would prefer a more polymorphic definition.

While Prelude could be modified to make it a better fit for modern Haskell, the implicit import of Prelude by every Haskell module means that making these changes will have a very wide impact. Furthermore, as the language continues to evolve, future changes that we want to make will also have the potential to break lots of code in the wild.

Also, there will always be some cut-off for which functions are included in the Prelude and which aren't. It would seem rather ad-hoc for some list functions, such as map, to be implicitly imported via Prelude, when other, less common functions, such as scanl1, require an implicit Data.List import. It would be more consistent to always require a Data.List import when using any list functions.

Finally, the Prelude is a very broad module; for example, it includes both pure combinators like map, and IO functions like putStrLn. There has recently been support for breaking the base package up, and this causes headaches about where to put Prelude. It doesn't belong in any other proposed package, but putting it in its own package (which every other package would then need to depend on) seems excessive.

We therefore suggest that modules no longer implicitly import Prelude.

This would make the language definition a little simpler, and remove a bit of magic.

It would also allow computer science courses to more easily use a simplified, more monomorphic Prelude replacement for teaching (or, when asking students to implement basic functions like length as exercises, no Prelude at all).

More generally, this would make adoption of the alternative preludes easier, by making a more level playing field.

It may also be beneficial to EDSL designers, who wish to reuse Prelude names for different functions.

Related issues

The sections below discuss issues related to the proposal, but which are not part of it.

Other changes to base

With the Prelude no longer implicitly imported, there are some functions which no longer seem to have a good home. For example, if you want to use (+) then you would have to import Prelude, which is a bit of a peculiar name. Having a new module Data.Num also export (+) would make more sense. We would encourage the library maintainers to go over the Prelude exports, and make new homes for Prelude exports that don't already have one.

The future of the Prelude module

If we stop Prelude being implicitly imported, then we could just leave the module unchanged, so it can still be explicitly imported.

The module would still export an odd selection of functions, but that could be fixed (and once it is no longer implicitly imported by every module, less breakage would be caused).

The other option would be to remove the module too. If, as mentioned above, base is split into smaller packages, then this would be the ideal time at which to remove it. After the split happens, a new base package would be created which just re-exports things from the new packages, so that existing code continues to work without change. Projects would be encouraged to switch to depending on the new packages, rather than base (which will be deprecated, will slowly drift out of sync with modern Haskell, and will stop being shipping with the Haskell Platform after a few releases).

We could therefore leave a Prelude module in the new base package, but not put a Prelude module in any of the new packages. Code moving to the new split packages would then need to import other modules instead. It may make sense to keep some very common things, such as the Show class (which is necessary whenever you want to define a datatype deriving Show) in a module with a more generic name, such as Core or Base. The name Prelude could also be used for this, but another name may sound more natural.


Currently, various pieces of Haskell syntax are desugared into expressions that reference entities in the Prelude. Note that it is not required that the entities are in scope, e.g.

import Prelude (IO, return)

main :: IO ()
main = do return ()
          return ()

is valid even though (>>) is not in scope.

Therefore no change is necessary if the implicit import of Prelude is dropped. If the module is also removed, then the report will have to refer to the entities in other locations for its desugaring.

Backwards compatibility

The breakup of the base package also provides an opportunity to improve the backwards compatibility that would be introduced by this change.

If base will now just re-exporting things from other packages then, like the haskell98 and haskell2010 packages, we presume that it would be hidden by default. We therefore suggest that these packages could provide a useful proxy for whether the ImplicitPreludeImport extension defaults to being enabled or not: if one of these packages is exposed, then it would be on (for backwards compatibility); otherwise it would be off.

Interactive environments

The Prelude is particularly useful in interactive environments, which many people like to use as a calculator. We would not want users to need to manually import several modules before they could use common functions like length and (+).

In the case of ghc/ghci, the interactive environment already differs from the compiler: In the interactive environment, the ExtendedDefaultRules extension is enabled by default. We recommend that interactive implementations should similarly import one or more modules by default. e.g. {Prelude} or {Data.Function, Data.List, Data.Num}.

This could either be built in to the compiler, or the interactive environment could use a config file for it. For example, ghci could create a ~/.ghci (if none exists) containing

set -XExtendedDefaultRules
import Prelude

Report Delta