简体   繁体   中英

basic Haskell : list comprehension

Me again, I'm trying to iterate through my list of customers to find the correct customer and when I find them I want to display any non-zero int's that are attached to them. I'm not sure how to proceed. I know there will only be 1 record of the person's name in the shop.

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']

It is very useful to read error message!

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

You have

getName (a, b) = a

but is defined

type Customer = (Name,Int,Int)

The right function looks like

getName (a, _, _) = a

After correct, you could see next 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'

But error is not in getNumbers , but in signature of rental:: Shop-> Name -> [Int] . Must be:

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

Your answer is pretty close. First of all, you need to update getName to take a 3-tuple, and second you should use concatMap getNumbers instead of map getNumbers .

Although, it looks like you're going to be adding new fields to your Customer type, so I would recommend that you switch to using a record instead:

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

And now you could get rid of getName and do

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']

Now if you were to add another field to Customer , you don't have to update all your functions that don't depend on that field.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM