Reputation: 149
i need help with haskell i'm kinda confused.
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:
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)
$ mailAccountUpdate macc x
retruns a list and not an IO MailAccount.functors
and fmap
yet.Is there a way to edit the data directly like 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 :
mail1 = mail2
This will override the data in mail1 with the data from mail2. but i dont know how to code it in haskell with data type.
Thank you everyone in advance for helping me.
Upvotes: 0
Views: 468
Reputation: 3247
Check you contacts function. It should be
contacts (_,x) = x
MailAccount is a tuple, with first element as person and second as contact. So it cannot be (,,x) but should be (_,x).
The below updatecontact definition is working fine.
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. The error would have been understood easily without IO.
Upvotes: 1
Reputation: 1753
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 protected]"("last","first")
[(1,("last1","first1")), (2,("last2","first2"))]
then using it you would:
> updatePersonContact person1 ("NEW","NEWW") 2
-- Person "[email protected]" ("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. Each Contact
now has an Id
that we can use for getting to the right contact.
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.
With m fn
we give them straight back as those don't need changing. But we're interested in contacts
so we pass it to this function updateContact id newfullName contacts
.
In updateContact
as inputs we have an Id
, FullName
and list of [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 () 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.
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
. If i
doesn't match id
then let's just leave those values alone and return them as they came.
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. :)
In Haskell lists are immutable which means every time you are given a list you must return a brand new list.
Upvotes: 2