Thaveesha Gamage
Thaveesha Gamage

Reputation: 43

retrieve an element from a list of tuple with more than 2 elements (Haskell)

I'm new to Haskell and need some help on this situation. I have the following list

-- create a type for bank account
type AcNo = String
type Name = String
type City = String
type Amnt = Int

type AcInfo = [(AcNo, Name, City, Amnt)]

-- function to get the data of bank accounts to a list of tuples
bankAccounts :: AcInfo
bankAccounts = [("oo1", "Sahan", "Colomb", 100),("002", "John", "Jafna", 200)]

My requirement is to get the amount corresponding to the account number, e.g., for 001 it should give 100.

The function I wrote was this

--Function to check the balance of a person
checkBalance :: bankAccounts -> AcNo -> Amnt
checkBalance dbase number = Amnt|(AcNo, Name, City, Amnt) <- dbase, AcNo==number}

The second line is where im stuck at which gives the error message

Syntax error in input (unexpected `|')

I'd like to have some help on this. Thanx.

Upvotes: 4

Views: 858

Answers (2)

Landei
Landei

Reputation: 54574

Additional to Greg's excellent answer I want to point out that you shouldn't use tuples for bigger sets of values that constitute a logical unit. I would suggest to have an Account type, e.g. using record syntax, which makes things like accessing elements or making account changes more convenient:

data Account = Account { acNo :: AcNo
                       , name :: Name
                       , city :: City
                       , amount :: Amnt
                       } deriving (Eq, Show)   

See http://learnyouahaskell.com/making-our-own-types-and-typeclasses#record-syntax for details.

Then you should write functions in terms of Account, not in terms of AcInfo, and use normal list functions. Often the extractor functions provided by the record are good enough, as in your example:

checkBalance :: [Account] -> AcNo -> Maybe Amnt
checkBalance dbase number = fmap amount $ find (\acc -> number == acNo acc) dbase

Here acNo acc gets the account number and amount acc gets the amount from an account.

Upvotes: 7

Greg Bacon
Greg Bacon

Reputation: 139441

Recall that names of Haskell types begin with capital letters, so the type of checkBalance should be

checkBalance :: AcInfo -> AcNo -> Amnt

In your question, you seem to aim at using a list comprehension, but you don't have the syntax quite right.

checkBalance dbase number = head [amnt | (acNo, name, city, amnt) <- dbase,
                                         acNo == number]

This definition is fine if an account is in dbase

*Main> checkBalance bankAccounts "oo1"
100

but blows up when it isn't.

*Main> checkBalance bankAccounts "001"
*** Exception: Prelude.head: empty list

A better type for checkBalance is

checkBalance :: AcInfo -> AcNo -> Maybe Amnt

to represent the general case, i.e., dbase may or may not contain number.

Upvotes: 6

Related Questions