1

YAMLチャンクを解析し、そこからRequestインスタンスを作成しようとしています。したがって、基本的に私は次のものを持っています(の実装FromJSON URIFromJSON RequestMethodおよびFromJSON 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 のおかげで、答えは次の 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 はクラス制限を独自に推測できたはずです。まだ、おそらく。

于 2012-10-08T06:37:14.273 に答える