Home > OS >  Not in scope: type constructor or class ‘Text’
Not in scope: type constructor or class ‘Text’

Time:08-25

I'm trying to learn Haskell, and I have been given functions but not told how to use them or what imports to use and trying to figure it out. I think the error I'm getting means my imports are incorrect and not sure if they are. Can someone tell me if I have the imports set correctly please. So I created the basic Stack project that runs someFunc. I created a new File for these functions I was given called Read.hs

module Code.Read where

import qualified Data.Text as T

--takes one Text (e.g. unprocessed input from file) and returns a list of text.
extractWords :: Text -> [Text]
extractWords t =  ws
  where
    ws = map Data.Text.toCaseFold $ filter (not . T.null)
         $ map cleanWord $ Data.Text.words t
    cleanWord = T.dropAround (not . isLetter)

--This uses the Format library and the fmt function. It is a formatting library. in this case it attaches a name (msg) to a list(of Text), line by line.
allWordsReport :: String -> [Text] -> Text
allWordsReport msg words =
  fmt $ nameF (Data.Text.Internal.Builder.fromString msg)  $ unlinesF words

Error I'm getting

/Users/jamesmurphy/Desktop/Summer/FP/Assignment1/A1/src/Code/Read.hs:5:17: error:
    Not in scope: type constructor or class ‘Text’
    Perhaps you meant ‘T.Text’ (imported from Data.Text)
  |
5 | extractWords :: Text -> [Text]
  |                 ^^^^

/Users/jamesmurphy/Desktop/Summer/FP/Assignment1/A1/src/Code/Read.hs:5:26: error:
    Not in scope: type constructor or class ‘Text’
    Perhaps you meant ‘T.Text’ (imported from Data.Text)
  |
5 | extractWords :: Text -> [Text]
  |                          ^^^^

/Users/jamesmurphy/Desktop/Summer/FP/Assignment1/A1/src/Code/Read.hs:8:14: error:
    Not in scope: ‘Data.Text.toCaseFold’
    No module named ‘Data.Text’ is imported.
  |
8 |     ws = map Data.Text.toCaseFold $ filter (not . T.null)
  |              ^^^^^^^^^^^^^^^^^^^^

/Users/jamesmurphy/Desktop/Summer/FP/Assignment1/A1/src/Code/Read.hs:9:28: error:
    Not in scope: ‘Data.Text.words’
    No module named ‘Data.Text’ is imported.
  |
9 |          $ map cleanWord $ Data.Text.words t
  |                            ^^^^^^^^^^^^^^^

/Users/jamesmurphy/Desktop/Summer/FP/Assignment1/A1/src/Code/Read.hs:12:30: error:
    Not in scope: type constructor or class ‘Text’
    Perhaps you meant ‘T.Text’ (imported from Data.Text)
   |
12 | allWordsReport :: String -> [Text] -> Text
   |                              ^^^^

/Users/jamesmurphy/Desktop/Summer/FP/Assignment1/A1/src/Code/Read.hs:12:39: error:
    Not in scope: type constructor or class ‘Text’
    Perhaps you meant ‘T.Text’ (imported from Data.Text)
   |
12 | allWordsReport :: String -> [Text] -> Text
   |                                       ^^^^

/Users/jamesmurphy/Desktop/Summer/FP/Assignment1/A1/src/Code/Read.hs:14:16: error:
    Not in scope: ‘Data.Text.Internal.Builder.fromString’
    No module named ‘Data.Text.Internal.Builder’ is imported.
   |
14 |   fmt $ nameF (Data.Text.Internal.Builder.fromString msg)  $ unlinesF words
   |      

So from my searching (Mostly on https://hackage.haskell.org/), I think that I should be using import qualified Data.Text as T for these functions, I also added the dependencies to the package.yaml file like so:

dependencies:
- base >= 4.7 && < 5
- text

library:
  source-dirs: src
  exposed-modules: 
    - Lib  
    - Code.Read
  other-modules: []
  dependencies:
    - text

I haven't done anything to the Main file yet as I was just trying to get this to compile first. This is probably a complete mess and I apologize if it is. If someone can tell me if the imports are correct or point me in the direction of the error I would greatly appreciate it. Thank you.

CodePudding user response:

You made a qualified import, indeed:

import qualified Data.Text as T

so that means that you refer to the Text type with T.Text, for example:

module Code.Read where

import qualified Data.Text as T
import qualified Data.Text.Internal.Builder as B

--takes one Text (e.g. unprocessed input from file) and returns a list of text.
extractWords :: T.Text -> [T.Text]
extractWords t =  ws
  where
    ws = map T.toCaseFold $ filter (not . T.null)
         $ map cleanWord $ T.words t
    cleanWord = T.dropAround (not . isLetter)

--This uses the Format library and the fmt function. It is a formatting library. in this case it attaches a name (msg) to a list(of Text), line by line.
allWordsReport :: String -> [T.Text] -> T.Text
allWordsReport msg words =
  fmt $ nameF (B.fromString msg)  $ unlinesF words

CodePudding user response:

It's quite common to import modules like Data.Text or Data.ByteString which have lots of functions defined which conflict with Prelude like this:

import Data.Text                  (Text)
import Data.Text                  qualified as T
import Data.ByteString            (ByteString)
import Data.ByteString            qualified as BS
import Data.Text.Internal.Builder (fromString)

--takes one Text (e.g. unprocessed input from file) and returns a list of text.
extractWords :: Text -> [Text]
extractWords t =  ws
  where
    ws = map T.toCaseFold $ filter (not . T.null)
         $ map cleanWord $ T.words t
    cleanWord = T.dropAround (not . isLetter)

--This uses the Format library and the fmt function. It is a formatting library. in this case it attaches a name (msg) to a list(of Text), line by line.
allWordsReport :: String -> [Text] -> Text
allWordsReport msg words =
  fmt $ nameF (fromString msg) $ unlinesF words

As a general rule, at least in production code, anything that's imported should be explicitly imported (import Data.Text (Text)) or imported qualified (import Data.Text qualified as T) so that it's easy for someone else reading the code to tell exactly where any imported definitions come from - I can either see directly that it's a Text function because it's prefixed with T. or I can see that Text comes from Data.Text by searching for Text in the imports.

  • Related