1

我正在尝试计算在银行内拥有账户的两个年龄段的人/客户的总余额。我可以让它显示符合要求的人员列表。

这些是构造函数

    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) = 

如果有任何帮助,我将不胜感激。

4

2 回答 2

3

如果您使用列表推导,这非常简单:

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]

除此之外,您可以应用莎拉的建议和使用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)))
于 2012-11-11T18:03:50.690 回答
1

我在这里推荐三件主要的事情:(a)使用记录类型而不是元组;(b) 使用标准实用函数来处理列表和其他标准类型;(c) 编写辅助函数以帮助使所有函数保持简短易读。

关于第一个建议:

data Person = Person { ni :: NI, age :: Age, balance :: Balance } deriving (Eq, Show)

现在,您不必为了得到一个人的年龄而进行任何元组模式匹配;此记录类型声明为您age :: Person -> Age提供balance :: Person -> Balance免费的功能。

第三个建议的例子:这里有一个计算aPerson是否在两个年龄之间的函数:

betweenAges :: Age -> Age -> Person -> Bool
betweenAges lo hi person = lo <= age person && age person <= hi

现在,使用那个辅助函数和标准filter函数,你可以得到所有两个年龄之间的人,如下所示:

filter (betweenAges 18 27) rbs

要获得Persons 列表的平衡,您可以使用标准summap函数:

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.ListData.Maybe; (b) 学习如何自己编写这些实用函数。为什么这样?因为 (a) 教你如何将问题分解成小的、可重用的部分,并且 (b) 教你理解这些程序从底部到顶部发生了什么。

于 2012-11-11T22:37:52.090 回答