Rick Po
Rick Po

Reputation: 59

Menu variable not in scope Haskell

I am trying to create a menu which read the data from a textfile. But I get three errors that variable not in scope despite having at the start of the IO(). Am I not reading the txt.file properly and is the way I creating the menu wrong?

errors

Variable not in scope: spaDatabase :: [Spa]

--line of error for spaDatabase
let updatedDB = (addSpa rid br ar (read st) spaDatabase)

Variable not in scope: spaDB
Variable not in scope: updatedDB :: [Spa]

--line of error for updatedDB
2 -> putStrLn (spaListStr updatedDB) >> menu spaDB

My code

main :: IO()
main = do 
       contents <- readFile "spa.txt"
       let spaDatabase = (read contents :: [Spa])
       menu spaDatabase
       putStrLn "" 
     where  menu spaDatabase = do
                putStrLn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
                putStrLn "\nPlease select an option:"
                putStrLn "1: Add a new spa to the database "       
                putStrLn "2: Show all spa "   
                putStr "\nSelected option: "
                putStrLn ""
                option <- getLine    
                putStrLn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
                
            output :: Int -> IO ()
            output option = do 
                case option of 1 -> do putStrLn "Enter Spa ID: "
                                       rid <- getLine
                                       putStrLn "Enter Spa Brand Name: "
                                       br <- getLine
                                       putStrLn "Enter Spa Area: "
                                       ar <- getLine
                                       putStrLn "Enter Spa Stars: "
                                       st <- getLine
                                       let updatedDB = (addSpa rid br ar (read st) spaDatabase)
                                       putStrLn (spaListStr updatedDB)
                                       writeFile "spa.txt" (spaListStr updatedDB)

                        
                               2 -> putStrLn (spaListStr updatedDB) >> menu spaDB
                    
   

Upvotes: 1

Views: 578

Answers (1)

Will Ness
Will Ness

Reputation: 71119

where is part of a definition, not of expression. It belongs to the main's definition so its scope goes above do's. Your originally posted code

main = do { .....
            let c = .....
            .....
          }
       where
          a = ....
          b = ....c....
          .....

is equivalent to

main = let {       -- where's translation
          a = ....
          b = ....c....
          .....
          }
       in
          do {
               .....
               let c = .....
               .....
             }

You're using c in b = ....c.... before it is introduced with let c = ....., i.e. outside of its scope region. That's an error, "variable not in scope".

update. let in do blocks is just a shortcut:

              do {
                   .....
                   let c = .....
                   .....
                 }

is the same as

              do {
                   .....
                   let c = .....
                   in do {
                           .....
                         }
                 }

The working code could be structured, as also @chi proposed in the comments, as

main = do { .....
            let c = .....
            .....
            let { a = ....
                  b = ....c....
                }
            .....
         }

That way a and b are in c's scope, so may use c as part of their definitions.

Upvotes: 1

Related Questions