1

銀行内に口座を持っている 2 つの年齢層の人々/顧客の合計残高を計算しようとしています。要件に該当する人のリストを表示するようにできます。

これらはコンストラクタです

    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]

それ以外は、サラのアドバイスと使用法mapsum元の関数に適用できます。

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

ここで私がお勧めする主なことが 3 つあります。(a)タプルの代わりにレコード型を使用する。(b)標準のユーティリティ関数を使用して、リストやその他の標準型を操作します。(c)補助関数を作成して、すべての関数を短く読みやすくする。

最初の推奨事項:

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

これで、人の年齢を取得するためだけにタプル パターン マッチングを実行する必要がなくなりました。このレコード型宣言により、関数が無料で取得age :: Person -> Ageされますbalance :: Person -> Balance

Person3 番目の推奨事項の例: これは、aが 2 つの年齢の間にあるかどうかを計算する関数です。

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

さて、その補助関数と標準filter関数を使用して、次のように 2 つの年齢のすべての人を取得できます。

filter (betweenAges 18 27) rbs

のリストのバランスを取得するには、標準と関数Personを使用できます。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

原則として、取り組んでいる問題を解決する方法を見つけるために苦労することは生産的ではありません。私が思うに、より生産的な戦略は次のPreludeとおりData.ListですData.Maybe。(b) これらのユーティリティ関数を自分で作成する方法を学びます。なぜこのように?(a) 問題を再利用可能な小さな断片に分割する方法を教え、(b) これらのプログラムで何が起こっているのかを理解することを教えてくれるからです。

于 2012-11-11T22:37:52.090 に答える