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.