0

我试图列出一堆不属于特定银行的数字。

这是我的代码

类型

     type NI = Int
     type Age = Int
     type Balance = Int
     type Person = (NI, Age, Balance)
     type Bank = [Person]
     type Market = [Bank]
     type Pop = [NI]

银行

     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)

     clyde :: Bank
     clyde = [(1, 73, 240)
           , (2, 18, -70)
           , (23, 30, 800)
           , (14, 16, 30)
           , (5, 24, 800)
           , (19, 81, 750)
           , (17, 49, 946)
           , (20, 59, -850)
           , (29, 24, -348)
           , (30, 76, -100)

    sco :: Pop
    sco = [1..20]

这是我检查 NI 是否不在银行中的代码

    bankFree :: Pop -> Market -> Pop
    bankFree [] x = []
    bankFree x [] = error "No Banks selected"
    bankFree x [[]] = []
    bankFree (x:xs) [[],((n,a,b):ys)] = if x == n then bankFree (xs) [[],ys]
                                else x : bankFree xs [[],ys]
    bankFree x [[],[]] = []
    bankFree (x:xs) (((n,a,b):ys):zs) = if x == n then bankFree (xs) ((ys):zs)
                                else if x /= n then x : bankFree xs ((ys):zs)
                                else bankFree (xs) zs

如果我运行 bankFree sco [rbs,clyde] 应该显示的是 [11,12,13,15,16,18,20] 但是出现的是 [2..20]

我不知道我做错了什么以及如何继续,所以任何关于此事的帮助将不胜感激

4

3 回答 3

5

同样,正如我在对您之前的问题的回答中所建议的那样,您遇到这么多困难的原因是您没有有效地将问题分解成更小的部分,并且您没有帮助自己使用标准实用程序管理列表的功能。你试图一次咬掉太大的一块,这使得它很难解决。

所以你想把你的问题分解成易于自己解决的子部分,然后将它们组合成大问题的大解决方案:

import Data.List (any)

type Market = [Bank]
type Bank = [Person]
data Person = Person { ni :: NI, age :: Age, balance :: Balance } 
    deriving (Eq, Show)

bankFree :: Pop -> Market -> Pop
bankFree pop banks = filter checkBanks pop
    where checkBanks n = not (any (bankHasNI n banks))

bankHasNI :: NI -> Bank -> Bool
bankHasNI n bank = any (\person -> ni person == n) bank

必读:

于 2012-11-11T23:07:19.227 回答
2

把它分解成更小的问题。此外,使用高阶函数而不是手动递归来使您的算法更易于理解:

inBank :: NI -> Bank -> Bool
ni `inBank` bank = any (\(ni', _, _) -> ni' == ni) bank

inMarket :: NI -> Market -> Bool
ni `inMarket` market = any (ni `inBank`) market

bankless :: Pop -> Market -> Pop
bankless pop market = filter (not . (`inMarket` market)) pop

如果你测试它,你会得到:

>>> bankless sco [rbs, clyde]
[11,12,13,15,16,18]
于 2012-11-11T23:09:51.603 回答
2

我想这是作业,所以仅仅为你解决问题是不行的,但这里有一些提示:

  • 它有助于将您的职能应该做的问题形式化:“鉴于这个人群和这些银行客户名单,他们中谁没有账户?”
  • bankFree鉴于上述问题表述,将函数视为过滤器变得很自然。这里有一些人,对于每个人,只有在没有银行账户的情况下才保留。

过滤列表可以通过多种不同的方式实现,对于初学者来说最简单的可能是使用列表推导:

bankFree :: Pop -> Market -> Pop
bankFree pop market = [p | p <- pop, not (isBankCustomer market p)]

应该读作:返回 Pop 中所有非银行客户的人。的定义isBankCustomer应该是:

isBankCustomer :: NI -> Market -> Bool   
isBankCustomer ni market = ?   

您在这里要做的是以某种方式检查 ni 是否存在于任何银行客户列表中。

于 2012-11-11T23:11:28.013 回答