2012-12-12 54 views
6

我正在寫一個data記錄給一個JIRAJSON對象。問題是,多個對象具有相同的名稱/值對標籤。例如:如何應對Haskell名稱空間?

(從捲曲返回並格式化)

{"expand":"schema,names" 
,"startAt":0 
,"maxResults":2 
,"total":74 
,"issues":[ 
      {"expand":"editmeta,renderedFields,transitions,changelog,operations" 
      ,"id":"183614" 
      ,"self":"https://10.64.16.44/rest/api/latest/issue/183614" 
      ,"key":"BNAP-339" 
      ,"fields":{"versions":[ 
            {"self":"https://10.64.16.44/rest/api/2/version/28240" 
            ,"id":"28240" 
            ,"name":"2012-12-07" 
            ,"archived":false 
            ,"released":false 
            } 
           ] 
        ,"status":{"self":"https://10.64.16.44/rest/api/2/status/1" 
           ,"description":"The issue is open and ready for the assignee to start work on it." 
           ,"iconUrl":"https://10.64.16.44/images/icons/status_open.gif" 
           ,"name":"Open" 
           ,"id":"1" 
           } 
        ,"description":"Do Re Mi Fa" 
        ,"resolution":null 
        } 
      } 
      ] 

當我構建了問題的相應的哈斯克爾data記錄我得到:

data Issue = Issue {expand :: String 
        ,id :: String 
        ,self :: String 
        ,key :: String 
        ,fields :: Fields 
        } deriving Generic 


data Version = Version {self :: String 
         ,id :: String 
         ,name :: String 
         ,archived :: Bool 
         ,released :: Bool 
         } deriving Generic 

和 'ID' 和 '自我' 的比賽。它發生在我身上,我可以通過更改記錄中的名稱並使用手動創建的FromJSON實例來解決此問題。 任何替代解決方案將受到歡迎。

回答

10

我在協議緩衝區中解決了這個問題,將IssueVersion這些東西放在同一層次結構中的單獨文件中。

Haskell只使用單獨的模塊來控制名稱空間,所以這是正統的解決方案。

很多很多票友:使用類型類來定義可用名稱:

class Has'self a b | a -> bwhere 
    get'self :: a -> b 
    set'self :: b -> a -> b 

instance Has'self Issue String where ... 
instance Has'self Version String where .... 

編輯:下面的評論提醒我要得到更詳細的建議。不要像解決方案一樣使用Has'self - 那些走過那條路的人報告它會變得醜陋。我可以保證單獨模塊的路徑。

PS:也許你可以使用lens庫爲你的領域!

+7

注意'HasFoobar'風格類型類幾乎都是一個可怕的想法,當談到編寫乾淨,結構良好的Haskell代碼。但是當試圖匹配非Haskell代碼的結構以用於互操作目的時,如果另一方嚴重依賴於重載函數和/或子類型層次結構,則可能沒有更好的方法。 –

+0

我在推薦你推薦單獨文件的部分。類型類是一種糟糕的命名空間解決方案,因爲它們對用戶來說非常難以推斷類型,並會在默認情況下失敗,並在應用於錯誤類型時做錯誤的事情。 –

3

另一個應該工作的方法是使用包含不同記錄的單一數據類型。例如,下面的數據類型能夠代表無場衝突的價值:

import Prelude hiding (id) 

data JIRA = JIRA 
    { expand :: String 
    , startAt :: Int 
    , maxResults :: Int 
    , total :: Int 
    , issues :: [JIRA] 
    } | Issue 
    { expand :: String 
    , id :: Int 
    , self :: String 
    , key :: String 
    , fields :: JIRA 
    } | Field 
    { versions :: [JIRA] 
    , status :: JIRA 
    , description :: String 
    , resolution :: Maybe String 
    } | Version 
    { self :: String 
    , id :: Int 
    , name :: String 
    , archived :: Bool 
    , released :: Bool 
    } | Status 
    { self :: String 
    , description :: String 
    , iconUrl :: String 
    , name :: String 
    , id :: Int 
    } 


yourExample = JIRA 
    { expand = "schema, names" 
    , startAt = 0 
    , maxResults = 2 
    , total = 74 
    , issues = [ Issue 
       { expand = "editmeta, etc..." 
       , id = 12345 
       , self = "https://xyz" 
       , key = "BLAH" 
       , fields = Field 
          { versions = [ Version 
              { self = "https://foobar" 
              , id = 1234 
              , name = "quux" 
              , archived = False 
              , released = False 
              } 
             ] 
          , status = Status 
            { self = "https://etc" 
            , description = "issue" 
            , iconUrl = "https://iconurl" 
            , name = "open" 
            , id = 1 
            } 
          , description = "another description" 
          , resolution = Nothing 
          } 
       } 
       ] 
    } 
+0

請注意,只有當所有'id'是相同類型('Int')並且所有'self'是相同類型('String')等時,以上纔有效。 –