2016-03-19 9 views
0

私はこの型変数

{ 
"items": [Day], 
"pageCount": Int, 
"totalCount": Int 
} 

またはこの

{ 
"items": [Order], 
"pageCount": Int, 
"totalCount": Int 
} 

ように見えるかもしれいずれかのJSONデータを持っていますFromJSONで使用するためのフィールドがありますが、さまざまなエラーが発生する中で、適切な方法を見つけることができませんでした。私は二つの問題がここにあります

No instance for (FromJSON a) arising from a use of ‘.:’ 
    Possible fix: 
     add (FromJSON a) to the context of the instance declaration 
    In the second argument of ‘(<$>)’, namely ‘x .: "items"’ 
    In the first argument of ‘(<*>)’, namely ‘Market <$> x .: "items"’ 
    In the first argument of ‘(<*>)’, namely 
     ‘Market <$> x .: "items" <*> x .: "pageCount"’ 
+1

が、それはあなたを伝えるものを、コンテキストに 'FromJSONをA'追加してください余分な句を追加しました。例えばOrderための固定インスタンスです:'インスタンスFromJSON A => FromJSONは(市場A) ... ' – user2407038

+0

ありがとうございます。私はそれが意味することを知らなかったし、それは簡単ではないと思った。これは、インスタンスを使用する私の最初の試みです、そして、私はちょうどそのインスタンスに関連するいくつかの "型が一致しませんでした"エラーを取り除いたので、それはそれより複雑であると思った。 –

答えて

1

を得るこれは、現在の状態で自分のコード

--{-# LANGUAGE FlexibleInstances #-} 
--{-# LANGUAGE MultiParamTypeClasses #-} 
--{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE OverloadedStrings #-} 
import   Data.Aeson 

data Typed = Typed {typeID::Int,name::String} deriving (Show,Eq) 
data Day = Day {orderCount::Int,lowPrice::Float,highPrice::Float, avgPrice:: Float,volume::Int,date::String} 
data Order = Order {price::Float,isBuy::Bool,location::Typed} deriving (Show,Eq) 
data Market a = Market {items::a,pageCount::Int,totalCount::Int} deriving (Show,Eq) 
-- Can be either Market [Order] or Market [Day] 
instance FromJSON (Market a) where 
    parseJSON (Object x) = Market <$> x .: "items" <*> x .: "pageCount" <*> x .: "totalCount" 
instance FromJSON Order where 
    parseJSON (Object x) = Order <$> x .: "price" <*> x .: "buy" <*> x .: "location" 
instance FromJSON Typed where 
    parseJSON (Object x) = Typed <$> x .: "id" <*> x .: "name" 
instance FromJSON Day where 
    parseJSON (Object x) = Day <$> x .: "orderCount" <*> x .: "lowPrice" <*> x .: "highPrice" 
    <*> x .: "avgPrice" <*> x .: "volume" <*> x .: "date" 

であり、これは現在のエラーです。最初はコンパイルエラーです:Market aのインスタンスがあると主張すると、市場のJSONシリアライズをaという任意の選択肢で解析する方法を知っているはずですが、これは実際には何かを解析したいので不可能ですpriceフィールドのコンテンツの価格を入力するにはaと入力してください。

instance FromJSON a => FromJSON (Market a) where 
    ... 

を、今、すべてが順調です:

は、私たちは私達が私達のインスタンス宣言に制約を加えることで解析する方法を知っている可能a年代を考慮に私達の注意を制限します。しかし、もう一つの問題があります。私たちはFromJSONを実装しましたが、それは非網羅的なマッチでいっぱいです!これを-Wallで実行して、GHCが私たちに不平を言うのを見てください。問題は、Object以外のものが入力された場合、各parseJSONは実際には例外で失敗します(解析の失敗ではなく、 "プログラム全体を爆破する"という失敗)。これは、我々が悪い振る舞いをすることを意味します。

λ> decode "1.0" :: Maybe Typed 
*** Exception: /home/jozefg/scratch/Aeson.hs:(24,3)-(25,39): Non-exhaustive patterns in function parseJSON 

これを修正するために、他のすべてのケースで明示的に失敗する別の句を追加することができます。より生産性の高いソリューションは、これらのインスタンスをすべて手書きしないことがあるかもしれません。なぜなら、それらはすべてかなり簡単で、代わりにaesonのジェネリックのサポートを使用するからです。ここで私はちょうど

instance FromJSON Order where 
    parseJSON (Object x) = 
    Order <$> x .: "price" <*> x .: "buy" <*> x .: "location" 
    parseJSON _ = mempty