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
Related
I want to use the <|> operator from Text.Parsec but I am also importing Control.Applicative which also contains a <|> operator. How do I make sure that the former operator shadows the latter assuming I don't want to use an ugly looking qualified import?
Options you have, in descending order of recommendation:
Switch to megaparsec, which is built up front around the existing Haskell functor / transformer classes, rather than defining that kind of stuff anew.
Hide the unnecessarily specific Parsec.<|>. You don't need it.
import Text.Parsec hiding ((<|>))
import Control.Applicative
Hide Applicative.<|> and use only the stuff from Control.Applicative that's not concerned with alternatives.
import Text.Parsec
import Control.Applicative hiding (Alternative(..))
The proper way to do this would either be a qualified import or an import with hiding
import qualified Control.Applicative as CA
import Text.Parsec
or if you don't want to use qualified
import Control.Applicative hiding ((<|>))
import Text.Parsec
Shadowing would not work because both imports live in the same namespace and therefore ghc cannot infer the correct choice of function, i.e. the one you meant.
To my knowledge shadowing only works in function blocks which generate a new scope.
Moreover the order of imports makes in a lazily evaluated language has its perils and even though I am no expert I would guess that if a library is imported depends whether if it is used or where it is used which would affect the order of import.
update:
If there was a name shadowing at the point of imports - then the order of imports would make a difference, which is something you are not used to in a lazily evaluated language, where usually the order of execution of pure functions is arbitrary (even though the imports are done at compile time as #TikhonJelvis pointed out).
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).
As Nikita Volkov mentioned in his question Data.Text vs String I also wondered why I have to deal with the different String implementations type String = [Char] and Data.Text in haskell. In my code I use the pack and unpack functions really often.
My question: Is there a way to have an automatic conversion between both string types so that I can avoid writing pack and unpack so often?
In other programming languages like Python or JavaScript there is for example an automatic conversion between integers and floats if it is needed. Can I reach something like this also in haskell? I know, that the mentioned languages are weakly typed, but I heard that C++ has a similar feature.
Note: I already know the language extension {-# LANGUAGE OverloadedStrings #-}. But as I understand this language extensions just applies to strings defined as "...". I want to have an automatic conversion for strings which I got from other functions or I have as arguments in function definitions.
Extended question: Haskell. Text or Bytestring covers also the difference between Data.Text and Data.ByteString. Is there a way to have an automatic conversion between the three strings String, Data.Text and Data.ByteString?
No.
Haskell doesn't have implicit coercions for technical, philosophical, and almost religious reasons.
As a comment, converting between these representations isn't free and most people don't like the idea that you have hidden and potentially expensive computations lurking around. Additionally, with strings as lazy lists, coercing them to a Text value might not terminate.
We can convert literals to Texts automatically with OverloadedStrings by desugaring a string literal "foo" to fromString "foo" and fromString for Text just calls pack.
The question might be to ask why you're coercing so much? Is there some why do you need to unpack Text values so often? If you constantly changing them to strings it defeats the purpose a bit.
Almost Yes: Data.String.Conversions
Haskell libraries make use of different types, so there are many situations in which there is no choice but to heavily use conversion, distasteful as it is - rewriting libraries doesn't count as a real choice.
I see two concrete problems, either of which being potentially a significant problem for Haskell adoption :
coding ends up requiring specific implementation knowledge of the libraries you want to use.This is a big issue for a high-level language
performance on simple tasks is bad - which is a big issue for a generalist language.
Abstracting from the specific types
In my experience, the first problem is the time spent guessing the package name holding the right function for plumbing between libraries that basically operate on the same data.
To that problem there is a really handy solution : the Data.String.Conversions package, provided you are comfortable with UTF-8 as your default encoding.
This package provides a single cs conversion function between a number of different types.
String
Data.ByteString.ByteString
Data.ByteString.Lazy.ByteString
Data.Text.Text
Data.Text.Lazy.Text
So you just import Data.String.Conversions, and use cs which will infer the right version of the conversion function according to input and output types.
Example:
import Data.Aeson (decode)
import Data.Text (Text)
import Data.ByteString.Lazy (ByteString)
import Data.String.Conversions (cs)
decodeTextStoredJson' :: T.Text -> MyStructure
decodeTextStoredJson' x = decode (cs x) :: Maybe MyStructure
NB : In GHCi you generally do not have a context that gives the target type so you direct the conversion by explicitly stating the type of the result, like for read
let z = cs x :: ByteString
Performance and the cry for a "true" solution
I am not aware of any true solution as of yet - but we can already guess the direction
it is legitimate to require conversion because the data does not change ;
best performance is achieved by not converting data from one type to another for administrative purposes ;
coercion is evil - coercitive, even.
So the direction must be to make these types not different, i.e. to reconcile them under (or over) an archtype from which they would all derive, allowing composition of functions using different derivations, without the need to convert.
Nota : I absolutely cannot evaluate the feasability / potential drawbacks of this idea. There may be some very sound stoppers.
I just realized that I can define my own Prelude module and carefully control its exports.
Is this considered bad practice?
Advantages:
No need to repeatedly import a "Common" module in large projects.
No need to write "import Prelude hiding (catch)".
In general its a bad idea, as you end up with code written in your own idioms that isn't going to be easy to maintain by others.
To communicate with others you need a shared language of symbols. The Prelude is our core language, so if you redefine it, expect confusion.
The exception to this rule would be when developing an embedded domain-specific language. There, making a custom Prelude is entirely a good idea, and is indeed why it is possible to redefine the Prelude (and inbuilt syntax) in the first place.
By all means have your own additional modules, but don't override the Prelude.