我在 Haskell 中创建了以下三种类型:
type Product = (Int, String, Float)
type Order = (Product, Int)
type Purchase = [Order]
想法是每个
Product
都有一个ID(Int
),一个名字(String
)和一个价格(Float
)。 Order
是给定 Int
的某个离散量 (Product
)。 Purchase
是 Order
s 的列表。
有了这个,我必须创建一个函数,它接受两个
Purchase
然后融合它们,返回另一个 Purchase
作为回报。例如,如果输入是[(product1, 2), (product1, 3), (product2, 4), (product2, 5), (product3, 10)]
,那么输出应该是[(product1, 5), (product2, 9), (product3, 10)]
。换句话说,它删除所有重复的Order
s,对所有数量求和,并输出结果“融合”Purchase
.
这是我目前拥有的功能。它不起作用,Haskell 指出了几个
Couldn't match type
错误。
fusePurchases :: Purchase -> Purchase -> Purchase
fusePurchases p1 p2 = let productsIds = nub [productId | (aproduct, _) <- p1 ++ p2, let productId = fst aproduct] in [(aproduct, sum [snd p | p <- p1 ++ p2, fst (fst p) == productId])
| productId <- productsIds, let aproduct = head [prod | prod <- map fst (p1 ++ p2), fst prod == productId]]
有什么问题吗?应该做哪些改变?什么是操作函数?
谢谢!
我尝试创建一个单一的功能,并使用列表理解将产品合并到一个具有独特元素的列表中,其中每个
Order
的所有数量的总和根据具有相同Order
的其他Product
s求和.
第一个错误:
MergeOrders.hs:10:107-114: error:
• Couldn't match type: (Int, String, Float)
with: (a1, b1)
Expected: (a1, b1)
Actual: Product
• In the first argument of ‘fst’, namely ‘aproduct’
In the expression: fst aproduct
In an equation for ‘productId’: productId = fst aproduct
• Relevant bindings include
productId :: a1 (bound at MergeOrders.hs:10:91)
|
10 | fusionPurchases p1 p2 = let productsIds = nub [productId | (aproduct, _) <- p1 ++ p2, let productId = fst aproduct] in [(aproduct, sum [snd p | p <- p1 ++ p2, fst (fst p) == productId])
| ^^^^^^^^
出现是因为
aProduct
的类型是 Product
,它是一个三元组 (Int, String, Float)
,但您已尝试将函数 fst
应用于它,而 fst
仅适用于对。在 Haskell 中,将 fst
应用于一对作品:
> fst (1,2)
1
但是将它应用于三元组不会:
> fst (1,2,3)
<interactive>:1:5: error:
• Couldn't match expected type: (a, b0)
with actual type: (a0, b1, c0)
• In the first argument of ‘fst’, namely ‘(1, 2, 3)’
In the expression: fst (1, 2, 3)
In an equation for ‘it’: it = fst (1, 2, 3)
• Relevant bindings include it :: a (bound at <interactive>:1:1)
其他两个错误都是由类似的问题引起的。在每种情况下,您都试图将
fst
应用于 Product
三元组。
您可能会发现定义
fst3
:
fst3 :: (a, b, c) -> a
fst3 (a, _, _) = a
有了这个定义,下面的类型检查就可以了:
fusionPurchases :: Purchase -> Purchase -> Purchase
fusionPurchases p1 p2
= let productsIds = nub [ productId | (aproduct, _) <- p1 ++ p2
, let productId = fst3 aproduct]
in [ (aproduct, sum [snd p | p <- p1 ++ p2, fst3 (fst p) == productId])
| productId <- productsIds
, let aproduct = head [ prod | prod <- map fst (p1 ++ p2)
, fst3 prod == productId]]