我正在尝试计算在银行内拥有帐户的两个年龄段的人/客户的总余额。我可以让它显示符合要求的人员名单。
这些是构造函数
type NI = Int
type Age = Int
type Balance = Int
type Person = (NI, Age, Balance)
type Bank = [Person]
这是银行
rbs :: Bank
rbs = [ (1, 73, 1000)
, (2, 18, -50)
, (3, 60, 190)
, (4, 26, 300)
, (5, 24, 456)
, (6, 32, 7500)
, (7, 41, -46)
, (8, 59, -850)
, (9, 44, 348)
, (10, 66, -1000)
, (11, 37, 20000)
, (12, 29, -245)
, (13, 55, 3090)
]
这是我递归检查银行的代码
equityA' :: Bank -> (Int, Int) -> Bank
equityA' ((n,a,b):xs) (0,0) = error "No ages were selected"
equityA' [] (x,y) = []
equityA' ((n,a,b):xs) (f, s) = if (f <= a) && (s >= a) then (n,a,b) : equityA' xs (f, s)
else equityA' xs (f, s)
如果我运行equityA'rbs(40,50),输出将是[(7,41,-46),(9,44,348)]
我正在努力做的是打印出那些人的总余额。我有一些代码,但我被困在实际的计算部分。
检查总数的代码。
equityAge :: Bank -> (Int, Int) -> Int
equityAge ((n,a,b):xs) (0,0) = error "No ages were selected"
equityAge [] (x,y) = 0
equityAge ((n,a,b):xs) (f, s) =
如果有任何帮助,我将不胜感激。
答案 0 :(得分:3)
如果您使用list comprehensions:
,这很简单equityAge :: Bank -> (Int,Int) -> Int
equityAge _ (0,0) = error "No ages were selected"
equityAge [] (x,y) = 0
equityAge x (f,s) = sum [ b | (n,a,b) <-x, f <= a, a <= s]
除此之外,您可以应用Sarah's advice并在原始功能上使用map
和sum
:
equityAge :: Bank -> (Int,Int) -> Int
equityAge _ (0,0) = error "No ages were selected"
equityAge [] (x,y) = 0
equityAge x (f,s) = sum (map(\(_,_,b) -> b) (equityA' x (f,s)))
答案 1 :(得分:1)
我建议这里有三件主要的事情:(a)使用记录类型而不是元组; (b)使用标准效用函数来处理列表和其他标准类型; (c)编写辅助功能,以帮助保持所有功能简短易读。
关于第一个建议:
data Person = Person { ni :: NI, age :: Age, balance :: Balance } deriving (Eq, Show)
现在你不必做任何一个元组模式匹配只是为了得到一个人的年龄;此记录类型声明可免费获取函数age :: Person -> Age
和balance :: Person -> Balance
。
第三条建议的例子:这是一个计算Person
是否在两个年龄之间的函数:
betweenAges :: Age -> Age -> Person -> Bool
betweenAges lo hi person = lo <= age person && age person <= hi
现在,使用该辅助功能和标准filter
功能,您可以获得两个年龄段之间的所有人:
filter (betweenAges 18 27) rbs
要获得Person
列表的余额,您可以使用标准sum
和map
函数:
sum (map balance somePersons)
所以完整的解决方案就是这样:
-- Note how much easier to read this is when you use sum, map, filter
-- and betweenAges!
equityAge :: Age -> Age -> Bank -> Balance
equityAge lo hi bank = sum (map balance (filter (betweenAges lo hi) bank))
-- This could be its own top-level function if you're going to reuse it
-- somewhere else, but here I'm putting it in a where declaration assuming
-- that it's a throwaway.
where betweenAges lo hi person = lo <= age person && age person <= hi
作为一般规则,努力寻找如何解决你所处理的问题并不富有成效。我认为,更具生产力的策略如下:(a)学习如Prelude
,Data.List
和Data.Maybe
等基本库中的功能解决问题; (b)学习如何自己编写这些实用功能。为什么这样?因为(a)教你如何将问题分解成小的,可重复使用的部分,并且(b)教你理解这些程序中从底部到顶部发生的事情。