[英]Editing data type in Haskell
我需要Haskell的帮助,我有点困惑。
我有这样的自定义类型/数据:
type Name = String
type LastName = String
type Mail = String
type FullName = (LastName, Name)
data Person = Person Mail FullName deriving (Show, Read)
type Contact = (FullName,Mail)
type MailAccount = (Person,[Contact])
假设邮件帐户存储在一个data_base中,我现在要更新联系人列表,而我不知道如何使用此签名来做到这一点:
updateContact :: Mail -> LastName -> Name ->MailAccount -> IO MailAccount
我尝试了这个:
updateContact l n m macc = do
x <- createPerson l n m
return $ mailAccountUpdate macc x
我创建了以下三个功能:
--return my list of contacts
contacts:: MailAccount->[Contact]
contacts (_,_,con) = con
createPerson l n m = do
return (Person m (l,n))
mailAccountUpdate acc x = do
return (x:contact acc)
$ mailAccountUpdate macc x
重新运行列表,而不是IO MailAccount。 functors
和fmap
。 有没有办法像OOP ex : MailAccount.contact()
这样直接编辑数据? 如果没有,我怎么能创建一个可以完成这项工作的功能。
有没有办法让例如两个具有相同类型的mailAccount并对其进行编码以在ghci终端中做到这一点:
mail1 = mail2
这将用mail2中的数据覆盖mail1中的数据。 但是我不知道如何用数据类型在haskell中编码。
预先感谢大家对我的帮助。
有一个更整洁的版本,但是我这样做是为了让它更加理解:
type Name = String
type LastName = String
type Mail = String
type Id = Int
type FullName = (LastName, Name)
type Contact = (Id, FullName)
data Person =
Person Mail FullName [Contact]
deriving (Show, Read)
updatePersonContact :: Person -> FullName -> Id -> Person
updatePersonContact (Person m fn contacts) newfullName id =
Person m fn (updateContact id newfullName contacts)
updateContact :: Id -> FullName -> [Contact] -> [Contact]
updateContact id newfullName contacts =
map (\(i, fn) ->
if i == id
then (i, newfullName)
else (i, fn)) contacts
person1 :: Person
person1 = Person "email@me.com"("last","first")
[(1,("last1","first1")), (2,("last2","first2"))]
然后使用它,您将:
> updatePersonContact person1 ("NEW","NEWW") 2
-- Person "email@me.com" ("last","first") [(1,("last1","first1")),(2,("NEW","NEWW"))]
我们更新了Person
来拥有[Contact]
的列表,因此现在联系人已附加到人员上。 现在,每个Contact
都有一个Id
,我们可以使用该Id
来找到正确的联系人。
您可以在输入中解构您的类型,例如updatePersonContact (Person m fn contacts)
因此现在我们可以使用重构人所需的所有位。 通过m fn
我们可以直接将其退回,因为这些不需要更改。 但是我们对contacts
感兴趣,因此我们将其传递给此函数updateContact id newfullName contacts
。
在updateContact
作为输入中,我们有一个Id
, FullName
和[Contact]
列表。 遍历列表的方法是使用map
因此在这里我们使用地图来逐一浏览我们的联系人列表。 map () contacts
()
必须是(1,("last1","first1")
a -> b
的函数,并且我们的a
第一次循环时是(1,("last1","first1")
因此您可以看到它具有2个值,我们通过\\(i, fn) ->
。 i == 1
和fn == ("last1","first1")
。它们会像任何循环一样在列表的每次迭代中更新。
下一部分我们检查i == id
,如果是,那么这就是我们要更新的联系人,因此我们返回(i, newfullName)
这是我们最初传递给updatePersonContact
新全名。 如果i
与id
不匹配,那么我们就不理会这些值,并在它们出现时返回它们。
map
是一个函子,因此您可能会发现它并不坏,您可能需要对其进行更多阅读才能更好地理解。 :)
在Haskell中,列表是不可变的,这意味着每次给您列表时,您都必须返回一个全新的列表。
检查您的联系人功能。 它应该是
contacts (_,x) = x
MailAccount是一个元组,第一个元素是person,第二个元素是contact。 因此它不能是( ,, x),而应该是(_,x)。
下面的updatecontact定义工作正常。
updateContact l n m macc = let myP = Person l (n,m)
newMacc = (myP,((n,m),l):contacts macc)
in return newMacc
我同意其他人的观点,即无需在定义中使用IO。 没有IO,该错误将很容易理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.