カスタムタイプaeson
のjsonファイルを生成および解析するためにライブラリを使用しています。Graph
ここに型定義があります。
type Id = Int
type Edge = (Id, Id)
type Scenario = [Id]
data Point = Point Int Int
data Vertex = Vertex {-# UNPACK #-}!Id {-# UNPACK #-}!Point deriving (Show)
data Graph = Graph Id [Vertex] Scenario deriving (Show)
実際、私はすべての頂点が 2D 空間に位置するオイラーおよび半オイラー グラフを使用しています。一言で言えば、Graph は Data.Graph を使用していますが、これは私の問題とは関係ありません。すべてのグラフには、他の多くのグラフからすばやく識別するための独自の ID があります。
これは、私のグラフに関する情報を含むjsonファイルの例です:
{
"id": 1,
"vertices": {
"3": {
"y": 12,
"x": 0
},
"2": {
"y": 16,
"x": 24
},
"1": {
"y": 12,
"x": 10
}
},
"scenario": [
1,
2,
3,
1
]
}
だから、ここにtoJSON
関数の私の実装があります:
import qualified Data.Text as T
instance ToJSON Graph where
toJSON (Graph id v s) = object [ "vertices" .= object (map vertexToPair v)
, "scenario" .= s
, "id" .= id
]
where
vertexToPair :: Vertex -> (T.Text, Value)
vertexToPair (Vertex id (Point x y)) =
(T.pack $ show id) .= object [ "x" .= x, "y" .= y]
しかし、実際にはjsonファイルからの解析に問題があります。主な問題は、特定のグラフがいくつの頂点にあるかわからないため、ハードコーディングできないことです。parseJSON
関数を書く最初の試みは次のとおりです。
instance FromJSON Graph where
parseJSON (Object v) = do
i <- parseJSON =<< v .: "id"
vs <- parseJSON =<< v .: "vertices"
sc <- parseJSON =<< v .: "scenario"
maybeReturn ((buildGraph i sc) <$> (parseVertices vs 1))
where
parseVertices :: Value -> Int -> Maybe [Vertex]
-- parseVertices (Object o) i = ???
parseVertices _ _ = Just []
buildGraph :: Int -> Scenario -> [Vertex] -> Graph
buildGraph i sc vertices = Graph i vertices sc
maybeReturn Nothing = mzero
maybeReturn (Just x) = return x
parseJSON _ = mzero
1
実際、プログラムがまだ次のすべてを解析している間に、頂点からカウントを開始して取得できると思いましたi
。しかし、これは良い選択ではありませvertex id
ん。そのようなデータを解析することさえ可能ですか? とにかく、私はこの問題の最も単純なケースでも立ち往生しました(から開始して を使用してインクリメントする場合)。1
vertex id
1
vertex ids
1
(+1)
大丈夫。これは、最大頂点 ID と最小頂点 ID を取得する方法です。
import qualified Data.Text.Read as TR
import qualified Data.Foldable as Foldable
minID :: [Either T.Text Int] -> Int
minID = Foldable.maximum
maxID :: [Either T.Text Int] -> Int
maxID = Foldable.minimum
ids :: Object -> [Either T.Text Int]
ids o = map ((fmap fst) . TR.decimal) (M.keys o)
すべての署名が一般化されているわけではありませんが、これは単なる例です。
この単純な問題のケースを解決するために、明日もう一度試してみます。とにかく、主な質問にはまだ答えが必要です:)