2

I want to read a matrix [[Int]] from a text file(this matrix is given in a project euler's problem), so I have the following code

parseInt :: String -> [Int]
parseInt [] = []
parseInt (x : xs) = [(ord x) - (ord '0')] ++ (parseInt xs)

main = do
  str <- readFile "11.dat" 
  print $ fmap parseInt (lines str)

this code works fine and I can output the matrix a read.

However, I want to change the main function, so I can reuse fmap parseInt (lines str) instead of repeating it in my code.

main = do
  str <- readFile "11.dat" 
  print b
  where b = fmap parseInt (lines str)

the compiler gives me an error

11.hs:37:34: error:
    Variable not in scope: str :: String
[Finished in 0.9s]

It seems that the feed operation str <- readFile "11.dat" causes this problem because when I read from a string directly the code works fine

main = do
  print b
  where b = fmap parseInt (lines "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08\n...01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48\n")

I can also with let

main = do
  str <- readFile "11.dat" 
  let b = fmap parseInt (lines str)
  print b

So how can I do that with that

duplode
  • 33,731
  • 7
  • 79
  • 150
calvin
  • 2,125
  • 2
  • 21
  • 38
  • https://stackoverflow.com/q/45306764/625403 was recently asked, which is another way to come to the same realization provided in pigworker's answer below. – amalloy Jul 26 '17 at 17:55

1 Answers1

4

This is a parsing issue. Haskell parses the offending code as

main = (do {str <- readFile "11.dat"; print b}) where {b = fmap parseInt (lines str)}

so that the only local variables in scope for the where clause are the pattern variables to the left of = (all none of them, but in general, you might have some).

Meanwhile str scopes only from its binding to the end of the do block. And that's why putting a let in the do block after that binding works just fine.

pigworker
  • 43,025
  • 18
  • 121
  • 214
  • thank you very much for pointing out and correcting my error. Following your advise, I did some search, and I find [this](https://stackoverflow.com/questions/8274650/in-haskell-when-do-we-use-in-with-let) maybe also a good reading – calvin Jul 26 '17 at 09:35
  • Another common fix is to make `b` a function and pass it `str` as an argument. – Daniel Wagner Jul 26 '17 at 16:46