基本的Haskell:列表理解

时间:2013-10-11 22:45:18

标签: haskell

我再次,我正在尝试遍历我的客户列表以找到正确的客户,当我找到它们时,我想显示附加到它们的任何非零int。我不知道该怎么办。我知道商店里只有1个人的姓名记录。

type Name = String
type Customer = (Name,Int,Int)
type Shop = [Customer]
shop = [cust1, cust2]

cust1 = ("Steve", 321, 123) :: Customer
cust2 = ("John", 0,678) :: Customer

getName :: Customer -> Name
getName (a, b,c) = a

getNumbers :: Customer -> [Int]
getNumbers (a,b,c) = filter (/=0) [b,c] 


rental:: Shop-> Name -> [Int]
rental shop' name' = map getNumbers [ x|x<-shop',getName x == name']

2 个答案:

答案 0 :(得分:4)

阅读错误信息非常有用!

test23.hs:10:9:
    Couldn't match type `(Name, t0)' with `(Name, Int, Int)'
    Expected type: Customer
      Actual type: (Name, t0)

你有

getName (a, b) = a

但已定义

type Customer = (Name,Int,Int)

正确的功能看起来像

getName (a, _, _) = a

正确之后,你可以看到下一个meassage:

test23.hs:17:26:
    Couldn't match type `[Int]' with `Int'
    Expected type: Customer -> Int
      Actual type: Customer -> [Int]
    In the first argument of `map', namely `getNumbers'
    ...
    In an equation for `rental'

但错误不在getNumbers中,而是在rental:: Shop-> Name -> [Int]的签名中。必须是:

rental:: Shop-> Name -> [[Int]]

答案 1 :(得分:2)

你的答案非常接近。首先,您需要更新getName以获取3元组,然后您应该使用concatMap getNumbers代替map getNumbers

虽然看起来您要在Customer类型中添加新字段,但我建议您切换到使用记录:

data Customer = Customer
    { custName :: Name
    , custVal1 :: Int  -- I don't know what these are, so use real names
    , custVal2 :: Int
    } deriving (Eq, Show)

现在你可以摆脱getName并做

getNumbers :: Customer -> [Int]
getNumbers c = filter (/= 0) [custVal1 c, custVal2 c]

rental :: Shop -> Name -> [Int]
rental shop' name' = concatMap getNumbers [x | x <- shop', custName x == name']

现在,如果您要向Customer添加其他字段,则不必更新所有不依赖于该字段的函数。