我定义了一个函数f
,它返回项price
的{{1}},该项x
存储在类型为[(String,String,Int)]
的价格列表中
a = String
x = String
price = Int
pricesList = [(a,x,price)]
f a x ((a1, x1, price):ys) | a == a1 && x == x1 = price
| otherwise = f a x ys
我必须将此功能应用于项目列表,但我被卡住了。这可能使用地图吗?我无法理解。
(唯一可以使用递归的函数是f)
修改。一些例子来澄清一点
pricesList = [("apple","ipod",100),("apple","iphone",200),("samsung","galaxy",200)]
moneySpent = [("harry",1985,"apple",["iphone","ipod"]),("george",1983,"samsung",["galaxy"])]
*Main> f "apple" "iphone" pricesList
200
我需要知道一个人通过定义新功能花了多少钱,让我们说spentBy
(并在其中使用f
)
*Main> spentBy "harry"
300
到目前为止我做了什么:
itsThePerson name (n,_,_,_) = name == n
infoFrom name = (head . filter (itsThePerson name)) moneySpent
brand (_,_,b,_) = b
product (_,_,_,p) = p
brandPerson = brand . infoFrom
productPerson = product . infoFrom
是否可以使用功能map
的{{1}}来了解某人购买的产品的价格总和?
(函数f
将是函数f
)
itemPrice
我是否正在朝着正确的方向思考?
答案 0 :(得分:3)
假设你有三个参数函数:
f :: a -> b -> c -> d
以及c
值列表 - list :: [b]
。假设我们希望将f
应用于列表中的每个项目,并使用固定的第一个和第二个参数。所以我们可以这样做:
map (f x y) list
其中x::a
和y::b
。
与你的案例的唯一区别是参数的顺序。对于此类问题,请使用flip
:
flip :: (a -> b -> c) -> (b -> a -> c)
--original function
f :: a -> b -> c -> d
--partial application
f x :: b -> c -> d
-- flip
flip (f x) :: c -> b -> d
--partial application again
(flip (f x) y) :: b -> d
map (flip (f x) y) list :: [d]
在你的情况下,它可能会导致类似map (flip (f a) prices) list
。
答案 1 :(得分:2)
如果您为f
提供了类型签名,那么您尝试执行的操作会更清楚。我将假设f
的第三个参数是(item #, description, price)
的列表。一个例子是:
priceList = [(1,"item 1", 1), (2,"item 2", 22), (3, "item 3", 333), (4, "item 4", 4444)]
然后我们计划映射的列表必须如下所示:
list = [(1,"item 1"), (3,"item 3"), (4, "item 4")]
我们可以这样映射list
:
map (\(itemId, desc) -> f itemId desc priceList) list
您可以改为编写f
来获取两个参数,将前两个参数组合成一个元组f (a,x) ((a1, x1, price):ys)
。您所需要的只是map f list
。
最后,您还没有处理价格不在列表中的情况。你可以这样做:
f _ _ _ = error "item not found"
答案 2 :(得分:1)
修改后的答案: 你要解决的整体问题,
在类型签名方面,给出:
f :: String -> String -> [(String, String, Int)] -> Int
你想要:
myLookup :: (String -> String -> [(String, String, Int)] -> Int) ->
[(String, String, Int)] -> [(String, String)] -> [Int]
其中第一个参数是查找函数f
,priceList和itemList,输出是价格列表。
myLookup f priceList itemList = map (\(itemId, itemName) ->
f itemId itemName priceList)
itemList
map
的第二个参数是一个lambda,它从itemList中提取两个属性,并使用f
查找值。
答案 3 :(得分:0)
我可以解决我的问题:
f a x ((a1, x1, price):ys) | a == a1 && x == x1 = price
| otherwise = f a x ys
使用了新功能f2
f2 a x = f a x pricesList
然后
pricesList = [("apple","ipod",100),("apple","iphone",200),("samsung","galaxy",200)]
moneySpent = [("harry",1985,"apple",["iphone","ipod"]),("george",1983,"samsung",["galaxy"])]
spentBy name = sum (map (f2 (brandPerson name)) (productPerson name))
itsThePerson name (n,_,_,_) = name == n
infoFrom name = (head . filter (itsThePerson name)) moneySpent
brand (_,_,b,_) = b
product (_,_,_,p) = p
brandPerson = brand . infoFrom
productPerson = product . infoFrom