Haskell-在列表中循环以映射新列表

时间:2018-10-12 18:57:15

标签: haskell

我正在研究Haskell初学者程序,该程序可以获取产品价格(即价格表)和购物车中商品条形码的列表的数据库,并生成商品价格列表。但是我编写的代码会产生类型错误,我将在下面介绍。首先,我的代码:

我首先定义相关类型:

type BarCode = Int
type Name = String
type Price = Int
type PriceList = [(BarCode,Name,Price)]
type CartItems = [BarCode]
type CartPrices = [(Name,Price)]

接下来,我开始编写主程序:

priceCart :: PriceList -> CartItems -> CartPrices
priceCart ((bc, n, p):xs) (b:bs) = map look (xs b)

look :: PriceList -> BarCode -> (Name, Price)
look [] barcode = ("None",0)
look ((bc, n, p):xs) barcode
    | bc == barcode = (n, p)
    | otherwise = look xs barcode

从本质上讲,我希望能够遍历条形码列表并为look的每个元素调用CartItems函数,并使用map函数构建列表。但是,我的知识并没有完全扩展到所有的前奏函数,所以我认为我在错误地使用map函数。实际上,我知道这一点,因为我遇到了编译错误(请参见下文)。但是现在,我还想知道是否丢失了如何正确遍历priceCart中的列表的方法-我应该像在look函数中一样使用递归吗?如果是这样,我对如何组合上述所有功能以产生所需的输出感到困惑。

Compile Errors

2 个答案:

答案 0 :(得分:2)

我认为您正在寻找的是将PriceList的第一个元素放在CartItems处,然后将PriceList的第二个元素放在CartItems处,然后等等。可以通过递归来完成,建立像这样的列表

priceCart :: PriceList -> CartItems -> CartPrices
priceCart [] _ = []
priceCart t@((bc, n, p):xs) (b:bs) = look t b : priceCart t bs

如您所见,PriceList上的模式匹配没有用,可以替换:

priceCart t (b:bs) = look t b : priceCart t bs

为什么这与您在这种情况下编写的方式不能与map一起使用?

因此map正在寻找一个函数,该函数可应用于输入列表中的每个元素。您的函数有两个参数,其中一个参数可以作为PriceList中的元素找到,即xs。但是,另一个参数b (BarCode)不是列表xs中的元素,并且map不能将其识别为函数的参数之一,因为它不是列表中要映射的元素。

答案 1 :(得分:2)

我认为您想在BarCode中查找每个PriceList。我期望priceList的结果与输入CartItems的长度相同。这非常适合map

通常为map :: (a -> b) -> [a] -> [b]。 在您的情况下,您需要map :: (BarCode -> (Name, Price)) -> [BarCode] -> [(Name, Price)]

您有一个[Barcode]类型的列表,所以没问题。您{em>几乎在BarCode -> (Name, Price)中具有类型look :: PriceList -> BarCode -> (Name, Price)的功能。关键点是,您将比较每个BarCode与相同的PriceList。因此,您可以写priceCart prices bs = map (look prices) bs,其中look prices :: BarCode -> (Name, Price)

部分应用程序经常使学习Haskell的人们绊倒。 look prices在匿名函数语法中等效于\barcode -> look prices barcodepriceslook提供了第一个参数,剩下的是仍然需要BarCode的函数。

您可以在可以使用map的任何地方使用显式递归-显式递归更为通用。在这种情况下,我发现带有map的版本更易于阅读。