2012-12-12 2 views
6

JIRAJSON 개체를 마샬링하기 위해 data 레코드를 쓰고 있습니다. 문제는 이름/값 쌍에 대해 여러 객체의 레이블이 동일하다는 것입니다.하스켈 이름 공간에 대처하는 방법은 무엇입니까?

(컬에서 반환 형식) 내가 얻는 문제에 대응 하스켈 data 기록을 구성 할 때

{"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 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 같은 것을 같은 계층 구조의 개별 파일에 넣어 프로토콜 버퍼에서 해결합니다.

하스켈은 네임 스페이스를 제어하기 위해서만 별도의 모듈을 사용하기 때문에 이것이 정통 솔루션입니다.

훨씬 많은 애호가 : 사용 형 클래스를 사용할 이름을 정의하려면

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를 솔루션처럼 사용하지 마십시오. 도로 보고서를 작성한 사람은 추악 해집니다. 별도의 모듈 경로를 보증 할 수 있습니다.

추신 : 아마도 귀하의 필드에 lens 라이브러리를 사용할 수 있습니다!

+7

참고 : 예를 들어, 다음 데이터 형식 필드 충돌없이 값을 표시 할 수있다. 그러나 interop 목적을 위해 non-Haskell 코드의 구조를 맞추려고 할 때, 다른 쪽이 오버로드 된 함수 및/또는 하위 유형 계층에 크게 의존한다면 더 나은 접근법이 없을 수 있습니다. –

+0

별도의 파일을 추천 한 부분을 upvoting했습니다. 유형 클래스는 사용자가 유형에 대해 추론하기가 매우 어렵고 잘못된 유형에 적용될 때 자동으로 실패하고 잘못된 작업을 수행하기 때문에 빈약 한 이름 공간 솔루션을 만듭니다. –

3

다른 대안으로는 고유 레코드가 포함 된 단일 데이터 형식을 사용하는 것이 좋습니다. 깨끗, 잘 구성된 하스켈 코드를 작성에 관해서 HasFoobar` 스타일 typeclasses 거의 항상 끔찍한 생각이다 '것을

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') 인 경우에만 작동한다는 점에 유의하십시오. –