ZeeeeeV
ZeeeeeV

Reputation: 381

Haskell Ending Loop Return

I am trying to stop my program from stopping after the loop in a function ends. Let me first give some background - After a recent failed attempt at Haskell (Here) i have been working through a number of tutorials and have been able to successfully create myself lists containing both a name and priority (Below, working Code - Apologies if the copy/paste has miss-indented it).

module Main where

-- Function Main, gather details, then print
main :: IO ()
main = do info <- gatherInfo
      let names = info
      putStrLn . unlines . map printDetails $ names

-- Function to Get the Info
gatherInfo :: IO [(String, Int)]
gatherInfo = do putStr "Name: "
            name <- getLine
            if name == "quit"
              then return []
              else do priority <- getPri
                      let info = (name,priority)
                      otherInfo <- gatherInfo
                      return $ info : otherInfo

 -- Function to get Priority                          
 getPri :: IO Int
 getPri = do putStr "Priority: "
        input <- getLine
        let parsed = reads input
        if parsed == []
          then do putStrLn "Incorrect Entry, please enter again"
                  getPri
          else return $ fst $ parsed !! 0


 --Function to print each detail
 printDetails :: (String, Int) -> String
 printDetails (name, priorityScore) = "Name: " ++ name ++ "Priority: " ++ show priorityScore

This code will print the following output(incl user input):

 Patient Name: test1
 Patient Priority: 1

 Patient Name: test2
 Patient Priority: 2

 Patient Name: quit

 Patient name: test1 Priority: 1
 Patient name: test2 Priority: 2

As you can see, the list items are entered and then upon entering 'quit' the code prints the list contents.

The problem i have is that upon entering 'quit' and printing the list items, when i enter back into the program the items have gone.

What i am trying to achieve is running the gatherInfo function, then printing the list (in its entirety) and then going back to the gatherInfo function to add another item. For example, my output may be like:

 Patient Name: test1
 Patient Priority: 1

 Patient name: test1 Priority: 1

 Patient Name: test2
 Patient Priority: 2

 Patient name: test1 Priority: 1
 Patient name: test2 Priority: 2

 Patient Name: quit (Quit program, doesn't matter what happens now)

I have made several attempts at implementing this; for example, calling my printDetails function during each gatherInfo loop to print 'info', but with little success. How can i implement this into my design?

Upvotes: 1

Views: 527

Answers (1)

Martinsos
Martinsos

Reputation: 1693

I suggest you do this:
Modify your gather info function so it takes info of only one patient.
Then create another function, let's call it main':

main' patients = do patient <- gatherInfo
                    if (fst patient == "quit") 
                       then return ()
                       else do 
                               let patients' = patient:patients   -- add patient to list of patients
                               putStrLn . unlines . map printDetails $ patients' -- print list of patients
                               main' patients'  -- continue

What are we doing here is remembering state of your program by passing parameter (this is how it is done in Haskell, as you have no states). Now your main function would look like this:

main = main' []   -- start with empty list of patients

You may notice that I presumed your function gatherInfo will return patient with name "quit" when user inputs "quit", however you can do that some other way

Upvotes: 1

Related Questions