haskell — ways to have a clean import block? (re-e

2019-03-25 02:38发布

问题:

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.

回答1:

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.



回答2:

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.



回答3:

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.