Almost every module in our code base has imports such as:
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Text as Text
I would like to define a local prelude so that Map, Set and Text are available to the modules importing that prelude. Apparently there is no way to do that in Haskell. So I am wondering how do people solve this problem in large Haskell code bases.
I'm going to answer this question, interpreted as literally as possible:
How do people solve this problem in large Haskell code bases?
Answer: they write
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Text as Text
at the top of each module which needs Map, Set, and Text.
In my experience, managing imports is not a significant part of the difficulty of working with large codebases. The effort of jumping to the import list and adding a line for Data.Map when you discover you need it is absolutely swamped by the effort of finding the right place in the codebase to make changes, knowing the full breadth of the codebase so you don't duplicate efforts, and finding ways to test small chunks of a large application in isolation.
Compared to the proposed alternative in the other answer (CPP), this way also has some technical advantages:
Less project lead-in time. The fewer surprises there are for the humans who join onto your project, the quicker they can get up and running and be independently useful.
Better tool support. If I see Foo.bar as an identifier somewhere, I can use my text editor's regex search to find out what import line made the Foo namespace available without fancy additions to include #included files. If I want to find all the files that depend on Some.Fancy.Module, I can learn that by grepping for Some.Fancy.Module. Build systems that do change detection don't need to know about the extra .h file when computing which files to watch. And so forth.
Fewer spurious rebuilds. If you have more imports than you actually use, this can cause GHC to rebuild your module even when it need not be rebuilt.
One solution is to define the import list in a CPP header.
N.B.: This answer is just to show what is technically possible; Daniel Wagner's answer is generally the better alternative.
For a package-level example:
my-pkg/
my-pkg.cabal
include/imports.h
src/MyModule.hs
...
include/imports.h:
import Control.Applicative
import Data.Maybe
import Data.Char
In my-pkg.cabal, components (library, executable, test, ...) have a include-dirs field (that in turn correspond to some GHC option):
library
...
include-dirs: include
Then you can use that header in any module:
{-# LANGUAGE CPP #-}
module MyModule where
#include "imports.h"
-- your code here
mymaybe = maybe
Recently I've been writing a lot of scripts in Haskell. It's quite an enjoyable experience as it is one of the most concise languages I've ever touched.
One thing that bothers me a lot though, is that I have to type in the same imports for every script I write, and there's a set of modules I use almost everytime, like
import Control.Monad as MO
import Data.ByteString.Lazy as BS
import Data.Char as CH
import Data.Csv as C
import Data.Csv.Streaming as CS
import Data.Foldable as FOLD
import Data.Functor as F
import Data.List as L
import Data.List.Split as LS
import Data.Text.Lazy as T
import Data.Text.Lazy.IO as TI
import Data.Vector as V
import Debug.Trace as TR
import Prelude as P
I mean I could copy and paste them every time, but is there a way I can make these tedious imports implicit? Just like how Prelude is imported implicitly?
One option for some purposes is to write one or more "kitchen sink" modules for your own use and just import that every time. Unfortunately, that doesn't seem to do much good when it comes to named or qualified imports. Another option is to use {-# LANGUAGE CPP #-} to #include some stock header pieces.
However, I wouldn't particularly recommend any of these options. Just keep a "stock template" around with your favorite GHC extensions and module imports, and teach your text editor to use it. Don't forget to prune away the stuff you don't actually need.
Ghci on acid defines in its .gchi
:set -XNoImplicitPrelude
What is the potential benefit/reason one might have for doing so ?
There is no other way to completely avoid importing the Prelude. Even the seemingly-effective
import Prelude ()
which is an explicit import (hence overrides the implicit one) and defines no names nevertheless puts a bunch of class instances in scope that may not be desired.
Avoiding the standard prelude completely is useful when you want to play around with alternate preludes; or when you want to overload syntax using other GHC extensions; or in other niche situations. Avoiding the prelude can also be useful if you plan on using many functions that happen to be named the same as the ones in the prelude, and would like to avoid qualifying them everywhere (though the lesser import Prelude () would suffice in many such situations).
Using Control.Applicative is very useful with Parsec, but you need to always hide <|> and similar objects as they conflict with Parsec's own:
import Control.Applicative hiding ((<|>), many, optional)
import Text.Parsec.Combinator
import Text.Parsec
Alternatively, as Antal S-Z points out, you can hide the Parsec version. However, as far as I can tell, this seems like an unnecessary restriction.
Why did parsec not simply implement these operators from Applicative?
It's for historic reasons. The Parsec library predates the discovery of applicative functors and so it wasn't designed with them in mind. And I guess no one has taken the time to update Parsec to use Control.Applicative. There is no deep fundamental reason for not doing it.
I'm often in the habit of having a standard import block, so I have commonly used functionality at hand when I need it. For example,
-- license block
{-# LANGUAGE Arrows,
DeriveDataTypeable,
EmptyDataDecls,
FlexibleContexts,
FlexibleInstances,
FunctionalDependencies,
GADTs,
MultiParamTypeClasses,
NoMonomorphismRestriction,
RankNTypes,
ScopedTypeVariables,
StandaloneDeriving,
TypeOperators,
TypeSynonymInstances,
UndecidableInstances,
ViewPatterns #-}
module MyModule where
import Prelude hiding (id, (.))
import Control.Arrow
import Control.Category
import Control.Exception
import Control.Monad
import Control.Monad.ST
import Data.Array.Diff
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Heap as Heap
import qualified Data.List as List
import qualified Data.List.Key as Key
import Data.List.HT
import Data.Maybe
import Data.STRef
import qualified Data.Text as T
Since I'm not using any fancy IDE's, I'd prefer not to read this in every file. Is there a way to create some kind of "standard" / "utility" module that re-exports the names of these functions, so I can just type,
import MyCommonFuncs
instead?
I know this is maybe not good practice, and maybe in theory one should add the minimial number of imports necessary, but as I said, I need to hack sometimes, and having fewer things to think about is always good.
EDIT -- more importantly, sometimes I want to change the block for all files, so the current system of importing everything individually can be tedious. Suppose, for example, that I need to remove the old import Time and change this to the new [sic?] import System.Time. Then, with the current system, I have to edit all files. Or, maybe I learn about a new language feature, and want that always available -- then I have to go manually update the older source files.
You can try using the Syntax
module MyCommonFuncs (
module Control.Arrow,
module Control.Category,
module Control.Exception,
module Control.Monad,
module Control.Monad.ST
)
import Control.Arrow
import Control.Category
import Control.Exception
import Control.Monad
import Control.Monad.ST
When you do this, all the functions in these modules are exported as if defined in the module MyCommonFuncs itself.
As for the LANGUAGE pragma, you can define the one you want in the .cabal file, they are used globally. Just not when testing via ghci.
Hope this helped.
You can certainly write a custom module that re-exports all those imports. This is in fact a common practice in the base libraries. See e.g. import Foreign,
module Foreign
( module Data.Bits
, module Data.Int
, module Data.Word
, module Foreign.Ptr
, module Foreign.ForeignPtr
, module Foreign.StablePtr
, module Foreign.Storable
, module Foreign.Marshal
...
The same can't be said for all those language extensions. Having all of those on by default isn't a good practice, in my opinion, since it almost guarantees you'll have non-portable, and compiler-sensitive code.
Gato,
Hmmm... I immediately thought #define, so I googled "haskell preprocessor", which produces a "promising" result.
I haven't got a clue if this a good answer (coz I don't know Haskell, at all), but it's almost certainly AN answer... I'll be interested to see what the gurus come up with.
Cheers mate. Keith.