我正在研究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
函数中一样使用递归吗?如果是这样,我对如何组合上述所有功能以产生所需的输出感到困惑。
答案 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 barcode
。 prices
为look
提供了第一个参数,剩下的是仍然需要BarCode
的函数。
您可以在可以使用map
的任何地方使用显式递归-显式递归更为通用。在这种情况下,我发现带有map
的版本更易于阅读。