Haskell-用户输入存储在列表中

时间:2018-07-26 15:17:35

标签: haskell

我正在寻求用户输入并将其存储为列表,以后可以搜索到。目前,我有一个名为“ sales”的空列表,该函数可以接受输入并将其存储在此列表中。

sales = []

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

此刻我得到一个

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

错误。现在已经解决了这个特殊错误,这是由于行

let sales = sales ++ [manufacturer, product]

但是,我不确定如何合并两个列表。即使当它正在“工作”时,在打印销售时我仍然得到一个空白清单。我不知道我是否在这里,特别是函数定义为“ IO()”。

这里的奖励部分是,如果我能够填充列表,那么我将如何搜索列表并显示某些元素,例如特定制造商的产品?

2 个答案:

答案 0 :(得分:6)

您无法在Haskell中对变量进行突变。所有Haskell变量都是不可变的。

-- `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

要了解为什么会导致循环,请考虑将sales的定义视为等式:sales = sales ++ [manufacturer, product]

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

您可能是这个意思:

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

但是,存储数据的通常方法是递归。我们会这样做(伪代码):

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 []

答案 1 :(得分:0)

@致癌物质是正确的。编译器认为,当您键入

let sales = sales ++ [manufacturer, product]

您是根据自身来定义sales

您似乎并没有存储其他条目,所以为什么不这样做

print [manufacturer, product]

因为您的程序之后立即退出了?

编辑:由于您希望程序继续运行,因此您将 必须更聪明地存储数据。 Haskell数据结构是不可变的。您可能想看看State monad,它以功能方式处理状态计算。