我需要创建一个电话簿作为元组列表:
type Phonebook :: [(String,String)]
正如您在代码中看到的那样,第一个元素应该代表名称,第二个元素代表数字。所以
的结果Main> phonebookone = insert "Dad" "90213" (insert "mum" "8912" emptyPhonebook)
Main> phonebookone
应为[("Dad","90213"),("mum","8912")]
但我只能获得[("Dad","90213")]
我的代码:
emptyPhonebook :: Phonebook
emptyPhonebook = [("","")]
insert :: String -> String -> Phonebook -> Phonebook
insert name number phonebook = [(name,number)]
我还需要创建一个函数search
,如果元组中的第一个元素存在于列表中并且与您搜索的字符串相同,则搜索数字或更好,它将导致元组的第二个元素。
所以它应该是:
Main> search "Dad" phonebook
"90213"
我未完成的代码:
search :: String -> Phonebook -> String
search name phonebook = if ..???
答案 0 :(得分:2)
你的代码有很多问题:
你的emptyPhonebook
实际上并非空:确实你已经在其中定义了一个元组:一个空字符串作为名称和电话号码。您可以将其更正为:
emptyPhonebook :: Phonebook
emptyPhonebook = []
您的插入方法insert
实际上创建了一个Phonebook
,其中包含一个条目:您要添加的条目,其余的电话簿将被忽略。您可以使用CONS((:)
)函数:
insert :: String -> String -> Phonebook -> Phonebook
insert name number = (:) (name,number)
现在回答主要问题。首先,大多数Haskell程序员认为if
更像是 un -Haskell:在Haskell中,使用模式匹配和 guards 来设定规则约束。
由于您的搜索可能在找不到具有该名称的人时发生错误(您没有指定),实际上我们必须考虑两个代码路径:
Haskell中的这些规则如下:
search query ((name,number):other) = ...
现在,如果query
和name
匹配,我们应该返回数字:
search query ((name,number):other) | query == name = number
在另一种情况下,我们递归地继续我们的崇高任务:
search query ((name,number):other) | otherwise = search query other
所以把它放在一起,你得到:
search :: String -> Phonebook -> String
search query ((name,number):other) | query == name = number
| otherwise = search query other
这将返回电话簿中给出的号码,否则会出错。
修改强>:
如果您希望在搜索失败时返回"error"
(作为字符串),则只需添加其他规则:
search _ [] = "error"
所以把它们放在一起给出了:
search :: String -> Phonebook -> String
search query ((name,number):other) | query == name = number
| otherwise = search query other
search _ [] = "error"
答案 1 :(得分:0)
如前所述,您的插入功能不完整,否则无论您尝试插入哪个功能,它都只有1条记录,因此如果您尝试在电话簿中搜索特定联系人,它只会检索到但是我不会回答这个问题,因为已经回答过了。
然后只需在电话簿上应用简单的递归
search :: String -> Phonebook -> String
search name ((contactName, contactNumber):phonebook) = if contactName == name then contactNumber else search name phonebook
或者您可以使用过滤器
search :: String -> Phonebook -> String
search name phonebook = snd . head . filter ((==name) . fst) $ phonebook
第二个选项的唯一问题是它将检索具有相同名称的第一个联系人,它可能不是我们要查询的那个,解决方法是使用Either String phonebook
作为返回如果有多个具有相同名称的个人,请输入以下内容:
search :: String -> Phonebook -> Either String phonebook
search name phonebook = let getContacts nm contacts = filter ((==nm) . fst) $ contacts
in case (length $ getContacts name phonebook) == 1 of
True -> Left $ snd . head . getContacts name $ phonebook
False -> Right $ (getContacts name) $ phonebook
忽略最后一个,未经测试,我认为不是你想要的,我只是添加了这个以防万一。“