1

我正在尝试解析 YAML 块并从中创建一个 Request 实例。所以基本上我有以下(的实现FromJSON URI,为了简洁FromJSON RequestMethodFromJSON Header省略):

...
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 #-}选项,但我以某种方式确定它是错误的。那么,我该如何正确解析这个(以及类似的情况)?

谢谢!

4

1 回答 1

3

感谢@hammar,答案归结为以下两点:

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 可以自己推断出类限制。还没有,也许。

于 2012-10-08T06:37:14.273 回答