1

我一直在与这个问题作斗争一段时间。我正在尝试创建一个“组织”,它是一个健身房列表。这些健身房是人员列表。每个人都有一个身份证号码、一个年龄和一个信用额度。

我希望 FindID 函数搜索组织以搜索 Gyms 列表以查找具有输入 ID 的用户,然后返回他们的信用总额。然而,我觉得我把问题复杂化了,我现在真的很挣扎。

newtype ID = ID Int deriving (Show)
newtype Age = Age Int deriving (Show)
newtype Credit = Credit Int deriving (Show)
newtype Person = Person (ID, Age, Weight) deriving (Show)   
type Gym = [Person]
type Organisation = [Gym]


getAge :: Person -> Int
getAge (Person(a,Age b,c)) = b

getID :: Person -> Int
getID (Person(ID a,b,c)) = a

getCredit :: Person -> Int
getCredit (Person(a,b,Credit c)) = c

p = Person ( ID 123, Age 65, Credit 12000)
q = Person ( ID 321, Age 64, Credit 0)
e = Person ( ID 453, Age 30, Credit 3000)
r = Person ( ID 123, Age 65, Credit 2310)
s = Person ( ID 364, Age 32, Credit 32340)
t = Person ( ID 123, Age 65, Credit 1300)
org1 = [p,q,e]
org2 = [r,s,t]


hasPerson :: Gym->Int-> Bool
hasPerson gym' id' = not (null(filter hasperson' gym') )
    where 
         hasperson' person' = getID person' == id'

findID:: ID -> Organisation -> Int
findID id' org = total
    where
         IsInGym org' = hasPerson ( org' id' )
         validGym =  filter (IsInGym) org'
         total = sum ( map getCredit validGym)
4

1 回答 1

1

首先,我建议使用记录来代表您的人,除非您有特殊原因为每个字段分配新类型:

type ID = Int
type Age = Int
type Credit = Int
data Person = Person
    { personId :: ID
    , personAge :: Age
    , personCredit :: Credit
    } deriving (Eq, Show)

type Gym = [Person]
type Organization = [Gym]

接下来,您可以使用map将 a 转换Gym[Int]with personId,然后您可以使用内置elem检查给定的 ID 是否出现在该列表中。

hasPerson :: Gym -> ID -> Bool
hasPerson gym pId = pId `elem` map personId gym

现在,对于该findID函数,我建议将其重命名为organizationCredit,并且我会创建一个更简单的函数来调用gymCredit它来为单个健身房计算它:

gymCredit :: ID -> Gym -> Credit
gymCredit pId gym = sum $ map personCredit $ filter (\p -> personId p == pId) gym

organizationCredit :: ID -> Organization -> Credit
organizationCredit pId org = sum $ map (gymCredit pId) org

或者,您可以将您的函数声明为

gymCredit :: Person -> Gym -> Credit
gymCredit person gym = sum $ map personCredit $ filter (\p -> personId p == pId) gym
    where pId = personId person

organizationCredit :: Person -> Organization -> Credit
organizationCredit person org = sum $ map (gymCredit person) org

编辑:要坚持使用旧类型,您只需自己定义一些额外的函数,然后将它们放入您需要的代码中

newtype ID = ID Int deriving (Eq, Show)
newtype Age = Age Int deriving (Eq, Show)
newtype Credit = Credit Int deriving (Eq, Show)
newtype Person = Person (ID, Age, Credit) deriving (Eq, Show)
type Gym = [Person]
type Organisation = [Gym]

personId :: Person -> ID
personId (Person (i, a, c)) = i

personAge :: Person -> Age
personAge (Person (i, a, c)) = a

personCredit :: Person -> Credit
personCredit (Person (i, a, c)) = c

idVal :: ID -> Int
idVal (ID x) = x

ageVal :: Age -> Int
ageVal (Age x) = x

creditVal :: Credit -> Int
creditVal (Credit x) = x

gymCredit :: Person -> Gym -> Credit
gymCredit person gym = Credit $ sum $ map (creditVal . personCredit) $ filter (\p -> personId p == pId) gym
    where pId = personId person

organisationCredit :: Person -> Organisation -> Credit
organisationCredit person org = Credit $ sum $ map (creditVal . gymCredit person) org

需要注意的是,我已将Eq每个新类型的派生类型类添加到列表中。没有它,您将无法直接比较两个IDs,您必须先提取值。要派生的另一个重要类型类是Ord,它允许您使用<><=>=运算符,以及一大堆列表函数,例如sort.

于 2013-10-06T15:26:27.760 回答