2011-09-02 71 views
2

,我有以下數據類型:埃宋fromJSON例如

data User = User { name :: T.Text, bookCount :: Int ,memberSince :: DateTime , 
    email :: T.Text, password :: B.ByteString } 
    | UnverifiedUser { nameUnverified :: T.Text, emailUnverified :: T.Text, 
    secret :: Integer } 

而下面的實例:

instance FromJSON User where 
    parseJSON (Object o) | Just _ <- M.lookup "secret" o = UnverifiedUser <$> o .: "name" <*> o .: "email" <*> o .: "secret" 
         | otherwise = User <$> o .: "name" <*> o .: "bookCount" <*> o .: "memberSince" <*> o .: "email" <*> o .: "password" 
    parseJSON _   = mzero 

但用戶被一分爲二,因爲有時在CouchDB中的文檔沒有某些字段像祕密或密碼。 我如何才能讓對數據類型的fromJSON實例:

data User = User { name :: T.Text, bookCount :: Int ,memberSince :: DateTime , 
     email :: T.Text, password :: B.ByteString , secret :: Integer } 

其中一些領域是強制性的,有些不是?

+0

您是否知道同一數據類型的不同構造函數可以共享記錄字段名(假設它們也共享記錄字段類型)?舉個例子,你可以寫'data User = Verified {name :: T.Text,email :: T.Text,...} |未經驗證{name :: T.Text,email :: T.Text}'。 –

+0

@Daniel:雖然這是正確的,但在一種數據類型中使用常見的東西並將不同的東西分解成另一種數據通常會更容易:data user = User {name :: T.Text,email :: T.Text ,驗證::驗證}'用'數據驗證=未驗證{祕密::整數} |已驗證{memberSince :: DateTime,password :: T.Text}'。 – hammar

+0

@丹尼爾,不,我沒有。但是我不相信未經驗證的用戶足以接受他的名字。 – Hai

回答

4

爲什麼不使用Maybe

data User = 
    User { 
    name   :: T.Text, 
    bookCount  :: Int , 
    memberSince  :: DateTime , 
    email   :: T.Text, 
    password  :: Maybe B.ByteString, 
    nameUnverified :: T.Text, 
    emailUnverified :: T.Text, 
    secret   :: Maybe Integer} 

instance FromJSON User where 
    parseJSON (Object o) = User <$> 
     o .: "name"   <*> 
     o .: "bookCount"  <*> 
     o .: "memberSince"  <*> 
     o .: "email"   <*> 
     o .:? "password"  <*> 
     o .: "nameUnverified" <*> 
     o .: "emailUnverified" <*> 
     o .:? "secret" 
+0

我最終做了一些有點不同的事情,但無論如何也使用了。 – Hai