簡體   English   中英

在Haskell中編輯數據類型

[英]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)
  1. 我的問題是,這些代碼無法正常工作,因為return $ mailAccountUpdate macc x重新運行列表,而不是IO MailAccount。
  2. 我還不夠熟練,無法使用functorsfmap
  3. 我想要一種方法來更新郵件帳戶中的聯系人列表,這意味着我想要一種方法來訪問和編輯此數據並用更新后的列表覆蓋它。
  4. 我必須尊重簽名,因此我嘗試使用終端中的邏輯,因此我嘗試了一些操作,所以我的問題是:

有沒有辦法像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作為輸入中,我們有一個IdFullName[Contact]列表。 遍歷列表的方法是使用map因此在這里我們使用地圖來逐一瀏覽我們的聯系人列表。 map () contacts

()必須是(1,("last1","first1") a -> b的函數,並且我們的a第一次循環時是(1,("last1","first1")因此您可以看到它具有2個值,我們通過\\(i, fn) ->i == 1fn == ("last1","first1") 。它們會像任何循環一樣在列表的每次迭代中更新。

下一部分我們檢查i == id ,如果是,那么這就是我們要更新的聯系人,因此我們返回(i, newfullName)這是我們最初傳遞給updatePersonContact新全名。 如果iid不匹配,那么我們就不理會這些值,並在它們出現時返回它們。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM