从包含超过2个元素的元组列表中检索一个元素(Haskell)

4

我是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}

我卡在第二行,出现了错误信息

输入语法错误(意外的“|”)

我需要一些帮助。谢谢。

2个回答

7

除了Greg的优秀回答之外,我想指出当您需要处理更大的值集合时,不应该使用元组。我建议使用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

请回忆一下,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

非常感谢您提供的帮助。是的,目前我只关注于账户是否在数据库中。我会尝试使用您提到的类型进行实验。再次感谢。 - Thaveesha Gamage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接