получить элемент из списка кортежей с более чем 2 элементами (Haskell) - PullRequest
4 голосов
/ 04 июля 2011

Я новичок в Haskell и мне нужна помощь в этой ситуации.У меня есть следующий список

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

Мое требование состоит в том, чтобы получить сумму, соответствующую номеру счета, например, для 001 это должно дать 100.

Функция, которую я написал, была этой

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

Вторая строка, в которой я застрял, выдает сообщение об ошибке

Syntax error in input (unexpected `|')

Я хотел бы помочь с этим.Thanx.

Ответы [ 2 ]

7 голосов
/ 04 июля 2011

В дополнение к отличному ответу Грега, я хочу отметить, что вы не должны использовать кортежи для больших наборов значений, которые составляют логическую единицу. Я бы предложил иметь тип Account, например используя синтаксис записей, что делает такие вещи, как доступ к элементам или внесение изменений в учетную запись более удобным:

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

Подробнее см. http://learnyouahaskell.com/making-our-own-types-and-typeclasses#record-syntax.

Затем вы должны написать функции в терминах Account, а не в AcInfo, и использовать обычные функции списка. Часто функции извлечения, предоставляемые записью, достаточно хороши, как в вашем примере:

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

Здесь acNo acc получает номер счета, а amount acc получает сумму со счета.

6 голосов
/ 04 июля 2011

Напомним, что имена типов Haskell начинаются с заглавных букв, поэтому тип checkBalance должен быть

checkBalance :: AcInfo -> AcNo -> Amnt

В вашем вопросе вы, похоже, стремитесь использовать понимание списка, но вы несинтаксис совершенно правильный.

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

Это определение подходит, если учетная запись находится в dbase

*Main> checkBalance bankAccounts "oo1"
100

, но взрывается, когда ее нет.

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

Лучшим типом для checkBalance является

checkBalance :: AcInfo -> AcNo -> Maybe Amnt

для представления общего случая, т.е. , dbase может содержать или не содержать number.

...