我需要在Haskell 但中编写2个函数,每个函数使用2个不同的方法(高滤波器和递归)。
我有2个元组来执行此操作:
材料是
(Model, Price, Accesories) :: (String, Int, [(String, Int)])
Accesory 是
(Name, Price) :: (String, Int)
第一个函数totalPrice
接收Material元组并具有
返回总价格(材料价格+配件价格)
示例:
主> totalPrice(“表”,150,[(“椅子”,100),(“椅子”,5)])
返回:totalPrice = 255
我已经通过递归制作了它:
totalPrice (_,x,l) = x + sum l
sum [] = 0
sum (t:ts) = snd t + sum ts
但我不知道如何使用高过滤功能。
第二个函数 expensiveMaterialsPrice 会收到一个列表 材料并且只能返回总价格的总和 昂贵的材料。 A
答案 0 :(得分:3)
您根本不需要totalPrice
的过滤器,我认为您正在寻找术语“高阶函数”。相反,您只需要一个功能来访问配件的价格:
accessoryPrice :: (String, Int) -> Int
accessoryPrice (_, price) = price
然后,您可以轻松地将配件列表转换为价格列表:
accessoryPrices :: [(String, Int)] -> [Int]
accessoryPrices accessories = map accessoryPrice accessories
现在,您可以在此输出上使用总和来获得总附件价格
totalAccessoryPrice :: [(String, Int)] -> Int
totalAccessoryPrice accessories = sum $ accessoryPrices accessories
我会留给你把它整合到你当前的代码中=)
有趣的是,accessoryPrice
只是snd
的一种更具体的形式,您可以用更短的形式编写此代码
totalAccessoryPrice = sum . map snd
但是你的意图远不那么明确。我现在高度建议使用更详细的表单,它有助于将问题分解为离散的步骤来解决,而不是试图立即解决整个解决方案。
对于expensiveMaterialsPrice
,您需要使用过滤器。在这种情况下,您应该创建一个函数isExpensive :: (String, Int, [(String, Int)]) -> Bool
来指示材料是否昂贵:
isExpensive :: (String, Int, [(String, Int)]) -> Bool
isExpensive material = totalPrice material > 1500
然后您可以使用isExpensive
作为filter
的谓词(第一个参数)。
可能有用的东西是创建一些类型别名:
type Name = String
type Price = Int
type Accessory = (Name, Price)
type Material = (Name, Price, [Accessory])
accessoryPrice :: Accessory -> Price
-- same definition
accessoryPrices :: [Accessory] -> [Price]
-- same definition
totalAccessoryPrice :: [Accessory] -> Price
-- same definition
totalPrice :: Material -> Price
-- your definition here
isExpensive :: Material -> Bool
-- same definition
它根本不会改变代码的含义,别名是可以互换的(即Price
和Int
是相同的类型,只是名称不同),但它确实减少了输入和制作你的意图很清楚。
答案 1 :(得分:0)
totalPrice
:
totalPrice (_,x,l) = x + (sum $ map snd l)
和expensiveMaterialsPrice
expensiveMaterialsPrice ms = sum $ map totalPrice $ filter isExpensive ms
where isExpensive m = totalPrice m > 1500