2012-10-06 43 views
1

我試圖解析一個YAML塊並從它創建一個請求實例。 所以基本上我有以下的(的FromJSON URIFromJSON RequestMethodFromJSON Header實現是爲了簡潔省略):解析JSON/YAML爲Network.HTTP.Base.Request

... 
instance FromJSON (Request r) where 
    parseJSON (Object v) = Request <$> 
    v .: "uri" <*> 
    v .: "method" <*> 
    v .: "headers" <*> 
    v .: "body" 

試圖編譯(使用GHC)此代碼產生:

No instance for (FromJSON r) 
     arising from a use of `.:' 
    In the second argument of `(<*>)', namely `v .: "body"' 
    In the expression: 
     Request <$> v .: "uri" <*> v .: "method" <*> v .: "headers" 
     <*> v .: "body" 
    In an equation for `parseJSON': 
     parseJSON (Object v) 
      = Request <$> v .: "uri" <*> v .: "method" <*> v .: "headers" 
      <*> v .: "body" 

我覺得這是一個新手問題(這就是我是誰),但顯然GHC不能推斷出請求主體的類型(這似乎是多態的),我缺乏處理這個問題的技能。雖然我設法用替代實例聲明「安撫」編譯:

instance FromJSON (Request Text) where 
... 

並添加{-# LANGUAGE FlexibleInstances #-}的選擇,但我敢肯定在某種程度上這是錯誤的。 那麼,我該如何正確解析這個(和類似的情況)呢?

謝謝!

+1

你有沒有試過給你的實例添加'FromJSON'約束?例如。 '實例FromJSON r => FromJSON(請求r)' – hammar

+0

它的工作!這是有道理的,並且代碼被編譯。我嘗試測試它: tj ::可能(請求一個) tj = decode「{uri:'http://example.com/',方法:GET,標頭:[],body:'hello'}」 ...但遇到錯誤: 沒有實例(FromJSON a)從使用'解碼」 在表達: 解碼 「{URI: '所產生的 http://example.com/',方法:GET,header:[],body:'hello'}「 在'tj'的公式中: tj = decode 」{uri:'http://example.com/',方法:GET,標題:[],正文:'你好'}「 我想知道我是否在正確的軌道上? –

+0

更新了測試函數聲明: 'TJ :: FromJSON一個=>也許(索取)' 現在它編譯,但輸出: 歧義類型變量'A0' 的約束: (FromJSON A0 )可能的修復:添加修復這些類型變量的類型簽名 在表達式中:tj 在'it'的等式中:it = tj 當我嘗試調用「TJ」。我擔心,這是一條錯誤的路。 –

回答

3

由於@hammar,答案歸結爲2個以下幾點:

1)爲了能夠加入計算,「R」(這是指請求主體)的實例聲明有限於「FromJSON」類。

instance FromJSON r => FromJSON (Request r) where 
    parseJSON (Object v) = Request <$> 
    v .: "uri" <*> 
    v .: "method" <*> 
    v .: "headers" <*> 
    v .: "body" 

2),所使用的解析器的時候,必須明確告知的身型是處理:

testJSON :: Maybe (Request Text) 
testJSON = decode "{uri: 'http://example.com/', method: GET, headers: [], body: 'hello'}" 

我不知道怎麼顯而易見的是,但GHC我想可以推斷出自己的類限制。也許還沒有。