Search code examples
haskelltextghcihaskell-prelude

Concisely give priority to non-Prelude functions in ghci


I have the following imports:

{-# LANGUAGE DeriveGeneric,  OverloadedStrings,  DefaultSignatures,  TypeOperators,  FlexibleContexts, RecordWildCards, FlexibleInstances, ExtendedDefaultRules #-}

import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Text
import GHC.Generics
import Data.DateTime
import Data.Aeson

I try to use the function lines to break on newline, and this function exists in both Prelude and Data.Text, and I get the following:

$ stack ghci
Prelude> :set -XOverloadedStrings
Prelude> :l mydat.hs
[1 of 1] Compiling Main             ( mydat.hs, interpreted )

mydat.hs:39:13: error:
    Ambiguous occurrence ‘lines’
    It could refer to either ‘Prelude.lines’,
                             imported from ‘Prelude’ at mydat.hs:1:1
                             (and originally defined in ‘base-4.11.1.0:Data.OldList’)
                          or ‘Data.Text.lines’,
                             imported from ‘Data.Text’ at mydat.hs:7:1-16
   |
39 |     print $ lines text
   |             ^^^^^
Failed, no modules loaded.

It's clear from the error message that this is failing because lines exists in both Prelude and Data.Text.lines.

What I'd like is to tell ghci to take /any/ function imported besides Prelude over any function defined in Prelude, particularly with text.

I thought one way to do this would be to explicitly, selectively hide Prelude.lines:

$ stack ghci
Prelude> :set -XOverloadedStrings -XNoImplicitPrelude
Prelude> import Prelude hiding (lines)
Prelude> :l mydat.hs
[1 of 1] Compiling Main             ( mydat.hs, interpreted )

mydat.hs:13:23: error:
    Not in scope: type constructor or class ‘Float’
    Perhaps you meant ‘UFloat’ (imported from GHC.Generics)

But this doesn't seem feasible: if I try to just hide one prelude function, I lose all the other functions I actually want.

What's the right way to keep Data.Text functions and hide them from collisions with Prelude.*? Am I stuck name-spacing everything with

import Data.Text as T

And using, for example:

T.lines 

?

If so, that seems a bit cumbersome, and would suggest making a Prelude package that is essentially PreludeWithoutPreludeText loading all the rest except this one--given the utility of OverloadedStrings.


Solution

  • This is not possible (speaking about GHC 8.6.4).

    One thing you may do is to qualify Prelude instead:

    import qualified Prelude
    

    optionally as P, which will require you to explicitly type Prelude. (or P.) before any name from this library.

    If you use other Prelude functions frequently you may hide only colliding identifiers by writing

    import Prelude hiding (lines)
    

    which will remove Prelude.lines from the namespace.

    If you want to use lines from Prelude somewhere in the file anyway, you could import this particular identifier as qualified:

    import           Prelude hiding (lines)
    import qualified Prelude as P (lines)
    

    I am afraid that it is everything you can do.