1

I'm looking to take a user input and store it as a list, which I would later be able to search. At the moment I have an empty list called "sales" and this function to take an input and store it in this list.

sales = []

recordPurchase ::  IO ()
recordPurchase = do
    putStrLn "Manufacturer"
    manufacturer <- getLine
    putStrLn "Product Name"
    product <- getLine
    let sales = sales ++ [manufacturer, product]
    print sales

At the moment I get an

"*** Exception: <<loop>>"

error. This particular error is solved now, it was due to the line

let sales = sales ++ [manufacturer, product]

However I'm not sure how to combine two lists it seems. Even when it was "working" I was still getting an empty list when sales was printed. I don't know whether I'm even on track here, particularly with the function definition as "IO()".

The bonus part here is if I was able to populate a list, how would I then be able to search it and display certain elements, such as products by a specific manufacturer?

3
  • My Haskell is pretty rusty, but wouldn't let sales = sales ++ create an infinite list? Sales is defined in terms of itself. Commented Jul 26, 2018 at 15:22
  • 1
    let sales = sales ++ [manufacturer, product] is the erroneous line. You're trying to change state. Haskell has no state. This is a recursive definition and therefore loops. Commented Jul 26, 2018 at 15:24
  • That'll be why I get the loop error, wasn't sure how to add a new list to a current one other than ++ Commented Jul 26, 2018 at 15:31

2 Answers 2

6

You cannot mutate variables in Haskell. All Haskell variables are immutable.

-- `sales` is now defined as `[]`. It cannot be changed, ever.
sales = []

recordPurchase ::  IO ()
recordPurchase = do
    putStrLn "Manufacturer"
    manufacturer <- getLine
    putStrLn "Product Name"
    product <- getLine
    -- Here, you define a new value called `sales`,
    -- which is recursively defined, since it refers to itself. 
    -- This causes a loop.
    let sales = sales ++ [manufacturer, product]
    print sales

To see why this causes a loop, consider the definition of sales as an equation: sales = sales ++ [manufacturer, product]:

  sales
= sales ++ [manufacturer, product]
= sales ++ [manufacturer, product] ++ [manufacturer, product]
= sales ++ [manufacturer, product] ++ [manufacturer, product] ++ [manufacturer, product]
= (etc)

What you probably mean is this:

recordPurchase ::  IO ()
recordPurchase = do
    putStrLn "Manufacturer"
    manufacturer <- getLine
    putStrLn "Product Name"
    product <- getLine
    print [manufacturer, product]

The usual way of storing data, however, is recursion. We'd do it a bit like this (pseudocode):

mainLoop :: [String] -> IO ()
mainLoop sales = do
    -- Get new sales info
    newInfo <- getNewInfo

    -- Define a new list with the extra info
    let newSales = sales ++ [newInfo]

    -- Do something with the sales info, e.g. print it
    print newInfo

    -- Go through the 'loop' again, with the new sales info.
    mainLoop newSales

 -- The main program is just the main loop with initial value of `[]`:
 main = mainLoop []
Sign up to request clarification or add additional context in comments.

Comments

0

@Carcigenicate is right. The compiler thinks that when you type

let sales = sales ++ [manufacturer, product]

you're defining sales in terms of itself.

You don't seem to be storing additional entries, so why not just do

print [manufacturer, product]

since your program exits right afterwards?

EDIT: Since you want to have your program keep running, you're going to have to be cleverer about storing data. Haskell data structures are immutable. You may want to check out the State monad, which handles stateful computations in functional way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.