2012-10-06 46 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我想可以推断出自己的类限制。也许还没有。