简体   繁体   English

在Haskell中编辑数据类型

[英]Editing data type in Haskell

i need help with haskell i'm kinda confused. 我需要Haskell的帮助,我有点困惑。

I have custom types/Data like this: 我有这样的自定义类型/数据:

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

Let's assume that mail account is stored in a data_base , what i want from now is update the list of contact and i don't know how to do it using this signature: 假设邮件帐户存储在一个data_base中,我现在要更新联系人列表,而我不知道如何使用此签名来做到这一点:

updateContact :: Mail -> LastName -> Name ->MailAccount -> IO MailAccount

I tried with this : 我尝试了这个:

updateContact l n m macc = do
           x <- createPerson l n m
           return $ mailAccountUpdate macc x

I created these three function: 我创建了以下三个功能:

 --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)
  1. My problem is that thes code won't work because return $ mailAccountUpdate macc x retruns a list and not an IO MailAccount. 我的问题是,这些代码无法正常工作,因为return $ mailAccountUpdate macc x重新运行列表,而不是IO MailAccount。
  2. I'm not skilled enough to play with the functors and fmap yet. 我还不够熟练,无法使用functorsfmap
  3. I want a way to update my list of contact in the mail account , meaning i want a way to access and edit this data and override it with the updated list. 我想要一种方法来更新邮件帐户中的联系人列表,这意味着我想要一种方法来访问和编辑此数据并用更新后的列表覆盖它。
  4. I have to respect the signature , so i tried to play with the logic in the terminal, so i tried a few things so my question is : 我必须尊重签名,因此我尝试使用终端中的逻辑,因此我尝试了一些操作,所以我的问题是:

Is there a way to edit the data directly like OOP ex : MailAccount.contact() ? 有没有办法像OOP ex : MailAccount.contact()这样直接编辑数据? if not how can i create a function that can do the work. 如果没有,我怎么能创建一个可以完成这项工作的功能。

Is there a way to have for example two mailAccount with the same type and code it to do the equivalent of this in the ghci terminal : 有没有办法让例如两个具有相同类型的mailAccount并对其进行编码以在ghci终端中做到这一点:

mail1 = mail2

This will override the data in mail1 with the data from mail2. 这将用mail2中的数据覆盖mail1中的数据。 but i dont know how to code it in haskell with data type. 但是我不知道如何用数据类型在haskell中编码。

Thank you everyone in advance for helping me. 预先感谢大家对我的帮助。

There is a neater version of this but I'm doing like this so it can be more understanding: 有一个更整洁的版本,但是我这样做是为了让它更加理解:

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

then using it you would: 然后使用它,您将:

> updatePersonContact person1 ("NEW","NEWW") 2
-- Person "email@me.com" ("last","first") [(1,("last1","first1")),(2,("NEW","NEWW"))]

We've update Person to have a list of [Contact] so now contacts are attached to a person. 我们更新了Person来拥有[Contact]的列表,因此现在联系人已附加到人员上。 Each Contact now has an Id that we can use for getting to the right contact. 现在,每个Contact都有一个Id ,我们可以使用该Id来找到正确的联系人。

You can deconstruct your types in the input like so updatePersonContact (Person m fn contacts) so now we can use all the bits we need to reconstruct our person. 您可以在输入中解构您的类型,例如updatePersonContact (Person m fn contacts)因此现在我们可以使用重构人所需的所有位。 With m fn we give them straight back as those don't need changing. 通过m fn我们可以直接将其退回,因为这些不需要更改。 But we're interested in contacts so we pass it to this function updateContact id newfullName contacts . 但是我们对contacts感兴趣,因此我们将其传递给此函数updateContact id newfullName contacts

In updateContact as inputs we have an Id , FullName and list of [Contact] . updateContact作为输入中,我们有一个IdFullName[Contact]列表。 the way to loop over a list is to use map so here we are using map to go through our list of contacts one by one. 遍历列表的方法是使用map因此在这里我们使用地图来逐一浏览我们的联系人列表。 map () contacts

the () needs to be a function from a -> b and our a when it loops the first time is (1,("last1","first1") so as you can see it has 2 values which we deal with by having \\(i, fn) -> . So i == 1 and fn == ("last1","first1") . These would update on every iteration of the list like any loop. ()必须是(1,("last1","first1") a -> b的函数,并且我们的a第一次循环时是(1,("last1","first1")因此您可以看到它具有2个值,我们通过\\(i, fn) ->i == 1fn == ("last1","first1") 。它们会像任何循环一样在列表的每次迭代中更新。

The next part we check if i == id and if it does then that's the contact we want to update so we return (i, newfullName) which is our new full name originally passed into updatePersonContact . 下一部分我们检查i == id ,如果是,那么这就是我们要更新的联系人,因此我们返回(i, newfullName)这是我们最初传递给updatePersonContact新全名。 If i doesn't match id then let's just leave those values alone and return them as they came. 如果iid不匹配,那么我们就不理会这些值,并在它们出现时返回它们。

map is a functor so as you might see it's not that bad you might need to do a bit more reading on it to get a better understanding. map是一个函子,因此您可能会发现它并不坏,您可能需要对其进行更多阅读才能更好地理解。 :) :)

In Haskell lists are immutable which means every time you are given a list you must return a brand new list. 在Haskell中,列表是不可变的,这意味着每次给您列表时,您都必须返回一个全新的列表。

Check you contacts function. 检查您的联系人功能。 It should be 它应该是

contacts (_,x) = x 

MailAccount is a tuple, with first element as person and second as contact. MailAccount是一个元组,第一个元素是person,第二个元素是contact。 So it cannot be ( , ,x) but should be (_,x). 因此它不能是( ,, x),而应该是(_,x)。

The below updatecontact definition is working fine. 下面的updatecontact定义工作正常。

updateContact l n m macc = let myP = Person l (n,m) 
                               newMacc = (myP,((n,m),l):contacts macc) 
                           in return newMacc

I agree with others that there is no need for using IO in definition. 我同意其他人的观点,即无需在定义中使用IO。 The error would have been understood easily without IO. 没有IO,该错误将很容易理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM