algebraic-graphs-io 0.4 → 0.5
raw patch · 8 files changed
+232/−47 lines, 8 filesdep +aesondep +serialisedep −QuickCheckdep −dotdep −matrix-market-attoparsecdep ~csv-conduitPVP ok
version bump matches the API change (PVP)
Dependencies added: aeson, serialise
Dependencies removed: QuickCheck, dot, matrix-market-attoparsec
Dependency ranges changed: csv-conduit
API changes (from Hackage documentation)
- Algebra.Graph.IO.Internal.Conduit: fetch :: MonadResource m => Request -> ConduitT i ByteString m ()
- Algebra.Graph.IO.Internal.Conduit: fetchTarGz :: String -> FilePath -> IO ()
- Algebra.Graph.IO.Internal.Conduit: unTarGz :: (PrimMonad m, MonadThrow m) => ConduitT ByteString TarChunk m ()
- Algebra.Graph.IO.Internal.Megaparsec: alphaNum :: Parser String
- Algebra.Graph.IO.Internal.Megaparsec: anyString :: Parser String
- Algebra.Graph.IO.Internal.Megaparsec: lexeme :: Parser a -> Parser a
- Algebra.Graph.IO.Internal.Megaparsec: symbol :: Text -> Parser Text
- Algebra.Graph.IO.Internal.Megaparsec: type ParseE = ParseErrorBundle Text Void
- Algebra.Graph.IO.Internal.Megaparsec: type Parser = Parsec Void Text
- Algebra.Graph.IO.Internal.Megaparsec: type ParserT = ParsecT Void Text
+ Algebra.Graph.IO.Internal: alphaNum :: Parser String
+ Algebra.Graph.IO.Internal: anyString :: Parser String
+ Algebra.Graph.IO.Internal: fetch :: MonadResource m => Request -> ConduitT i ByteString m ()
+ Algebra.Graph.IO.Internal: fetchTarGz :: String -> FilePath -> IO ()
+ Algebra.Graph.IO.Internal: lexeme :: Parser a -> Parser a
+ Algebra.Graph.IO.Internal: symbol :: Text -> Parser Text
+ Algebra.Graph.IO.Internal: type ParseE = ParseErrorBundle Text Void
+ Algebra.Graph.IO.Internal: type Parser = Parsec Void Text
+ Algebra.Graph.IO.Internal: type ParserT = ParsecT Void Text
+ Algebra.Graph.IO.Internal: unTarGz :: (PrimMonad m, MonadThrow m) => ConduitT ByteString TarChunk m ()
+ Algebra.Graph.IO.JSON: instance (Data.Aeson.Types.FromJSON.FromJSON e, Data.Aeson.Types.FromJSON.FromJSON a) => Data.Aeson.Types.FromJSON.FromJSON (Algebra.Graph.Labelled.Graph e a)
+ Algebra.Graph.IO.JSON: instance (Data.Aeson.Types.ToJSON.ToJSON a, Data.Aeson.Types.ToJSON.ToJSON e) => Data.Aeson.Types.ToJSON.ToJSON (Algebra.Graph.Labelled.Graph e a)
+ Algebra.Graph.IO.JSON: instance (Data.Aeson.Types.ToJSON.ToJSON e, Data.Aeson.Types.ToJSON.ToJSON a) => Data.Aeson.Types.ToJSON.ToJSON (Algebra.Graph.IO.JSON.LEdge e a)
+ Algebra.Graph.IO.JSON: instance (GHC.Classes.Eq e, GHC.Classes.Eq a) => GHC.Classes.Eq (Algebra.Graph.IO.JSON.LEdge e a)
+ Algebra.Graph.IO.JSON: instance (GHC.Show.Show e, GHC.Show.Show a) => GHC.Show.Show (Algebra.Graph.IO.JSON.LEdge e a)
+ Algebra.Graph.IO.JSON: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Algebra.Graph.Graph a)
+ Algebra.Graph.IO.JSON: instance Data.Aeson.Types.ToJSON.ToJSON Algebra.Graph.IO.JSON.Empty
+ Algebra.Graph.IO.JSON: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Algebra.Graph.Graph a)
+ Algebra.Graph.IO.JSON: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Algebra.Graph.IO.JSON.Connect a)
+ Algebra.Graph.IO.JSON: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Algebra.Graph.IO.JSON.Overlay a)
+ Algebra.Graph.IO.JSON: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Algebra.Graph.IO.JSON.Vertex a)
+ Algebra.Graph.IO.JSON: instance GHC.Classes.Eq Algebra.Graph.IO.JSON.Empty
+ Algebra.Graph.IO.JSON: instance GHC.Classes.Eq a => GHC.Classes.Eq (Algebra.Graph.IO.JSON.Connect a)
+ Algebra.Graph.IO.JSON: instance GHC.Classes.Eq a => GHC.Classes.Eq (Algebra.Graph.IO.JSON.Overlay a)
+ Algebra.Graph.IO.JSON: instance GHC.Classes.Eq a => GHC.Classes.Eq (Algebra.Graph.IO.JSON.Vertex a)
+ Algebra.Graph.IO.JSON: instance GHC.Generics.Generic (Algebra.Graph.IO.JSON.Connect a)
+ Algebra.Graph.IO.JSON: instance GHC.Generics.Generic (Algebra.Graph.IO.JSON.LEdge e a)
+ Algebra.Graph.IO.JSON: instance GHC.Generics.Generic (Algebra.Graph.IO.JSON.Overlay a)
+ Algebra.Graph.IO.JSON: instance GHC.Generics.Generic (Algebra.Graph.IO.JSON.Vertex a)
+ Algebra.Graph.IO.JSON: instance GHC.Generics.Generic Algebra.Graph.IO.JSON.Empty
+ Algebra.Graph.IO.JSON: instance GHC.Show.Show Algebra.Graph.IO.JSON.Empty
+ Algebra.Graph.IO.JSON: instance GHC.Show.Show a => GHC.Show.Show (Algebra.Graph.IO.JSON.Connect a)
+ Algebra.Graph.IO.JSON: instance GHC.Show.Show a => GHC.Show.Show (Algebra.Graph.IO.JSON.Overlay a)
+ Algebra.Graph.IO.JSON: instance GHC.Show.Show a => GHC.Show.Show (Algebra.Graph.IO.JSON.Vertex a)
+ Algebra.Graph.IO.Serialise: instance (Codec.Serialise.Class.Serialise e, Codec.Serialise.Class.Serialise a) => Codec.Serialise.Class.Serialise (Algebra.Graph.Labelled.Graph e a)
+ Algebra.Graph.IO.Serialise: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Algebra.Graph.Graph a)
Files
- CHANGELOG.md +9/−0
- algebraic-graphs-io.cabal +12/−10
- src/Algebra/Graph/IO/Datasets/LINQS.hs +1/−4
- src/Algebra/Graph/IO/Dot.hs +0/−29
- src/Algebra/Graph/IO/Internal.hs +7/−0
- src/Algebra/Graph/IO/JSON.hs +135/−0
- src/Algebra/Graph/IO/MatrixMarket.hs +0/−4
- src/Algebra/Graph/IO/Serialise.hs +68/−0
CHANGELOG.md view
@@ -1,3 +1,12 @@+* 0.5++ - no 'Dot' and 'matrix-market' support for now: + Dot/graphviz export is already supported within algebraic-graphs and matrix-market can be made available on a need basis+ + - add JSON codec+ + - add 'serialise'-based binary codec+ * 0.4 LINQS datasets :
algebraic-graphs-io.cabal view
@@ -1,5 +1,5 @@ name: algebraic-graphs-io-version: 0.4+version: 0.5 synopsis: I/O utilities and datasets for algebraic-graphs description: I/O utilities and datasets for algebraic-graphs. See README for details homepage: https://github.com/ocramz/algebraic-graphs-io@@ -19,24 +19,25 @@ assets/simulated_blockmodel_graph_50_nodes_truePartition.tsv assets/simulated_blockmodel_graph_50_nodes.tsv cabal-version: >=1.10-tested-with: GHC == 8.8.4+tested-with: GHC == 8.8.4, GHC == 9.0.2 library default-language: Haskell2010 ghc-options: -Wall hs-source-dirs: src exposed-modules: Algebra.Graph.IO.GML- Algebra.Graph.IO.Dot Algebra.Graph.IO.Datasets Algebra.Graph.IO.Datasets.LINQS Algebra.Graph.IO.Datasets.LINQS.Citeseer Algebra.Graph.IO.Datasets.LINQS.Cora- Algebra.Graph.IO.MatrixMarket+ Algebra.Graph.IO.JSON+ Algebra.Graph.IO.Serialise Algebra.Graph.IO.SV- Algebra.Graph.IO.Internal.Conduit+ Algebra.Graph.IO.Internal+ other-modules: Algebra.Graph.IO.Internal.Conduit Algebra.Graph.IO.Internal.Megaparsec- other-modules: - build-depends: algebraic-graphs+ build-depends: aeson+ , algebraic-graphs , attoparsec , base >= 4.7 && < 5 , binary@@ -47,15 +48,14 @@ , containers , csv-conduit , directory- , dot , exceptions , filepath , http-conduit- , matrix-market-attoparsec , megaparsec , mtl , parser-combinators , primitive+ , serialise , tar-conduit , text , transformers@@ -68,9 +68,11 @@ hs-source-dirs: test main-is: Spec.hs build-depends: base+ , aeson+ , algebraic-graphs , algebraic-graphs-io , hspec- , QuickCheck+ , serialise source-repository head type: git
src/Algebra/Graph/IO/Datasets/LINQS.hs view
@@ -56,14 +56,11 @@ -- tar-conduit import Data.Conduit.Tar (Header(..), untarChunks, TarChunk, withEntries, FileInfo, filePath, withFileInfo, headerFileType, FileType(..), headerFilePath) -- text- import qualified Data.Text as T (Text, unwords) --- transformers -import Algebra.Graph.IO.Internal.Conduit (fetch, unTarGz)-import Algebra.Graph.IO.Internal.Megaparsec (Parser, ParserT, ParseE, symbol, lexeme, alphaNum)+import Algebra.Graph.IO.Internal (fetch, unTarGz, Parser, ParserT, ParseE, symbol, lexeme, alphaNum) import Algebra.Graph.IO.SV (parseTSV) {-
− src/Algebra/Graph/IO/Dot.hs
@@ -1,29 +0,0 @@-{-# language OverloadedStrings #-}-{-# options_ghc -Wno-unused-imports #-}-module Algebra.Graph.IO.Dot where--import Dot (DotGraph(..), Strictness(..), Directionality(..), Statement(..), Element(..), NodeStatement(..), EdgeStatement(..), Attribute(..), Id(..))---{--main :: IO ()-main = do- putStrLn $ "dumping example dotgraph to " ++ target- encodeToFile target example- -target :: FilePath-target = "example/example.dot"--example :: DotGraph-example = DotGraph Strict Directed (Just "foobar")- [ StatementNode $ NodeStatement "a1"- [ Attribute "color" "blue"- , Attribute "shape" "box"- ]- , StatementNode $ NodeStatement "a2" []- , StatementEdge $ EdgeStatement (ListTwo "a1" "a2" ["a3"])- [ Attribute "color" "red"- ]- ]---}
+ src/Algebra/Graph/IO/Internal.hs view
@@ -0,0 +1,7 @@+module Algebra.Graph.IO.Internal (+ module Algebra.Graph.IO.Internal.Conduit,+ module Algebra.Graph.IO.Internal.Megaparsec+ ) where++import Algebra.Graph.IO.Internal.Conduit+import Algebra.Graph.IO.Internal.Megaparsec
+ src/Algebra/Graph/IO/JSON.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE DeriveGeneric #-}+{-# language OverloadedStrings #-}+{-# options_ghc -Wno-unused-imports #-}+{-|+Module : Algebra.Graph.IO.JSON+Description : 'aeson' instances for algebraic-graphs types+Copyright : (c) Marco Zocca, 2022+Maintainer : ocramz+Stability : experimental+Portability : POSIX++Orphan instances for compatibility between 'algebraic-graphs' and 'aeson'.++Import only if you know what you're doing.+-}+module Algebra.Graph.IO.JSON () where++import Control.Applicative (Alternative(..))+import GHC.Generics (Generic)++-- aeson+import qualified Data.Aeson as A (FromJSON(..), ToJSON(..), encode, eitherDecode, Value, withArray, withText, withObject, (.:), Object)+import qualified Data.Aeson.Types as A (Parser)+import qualified Data.Aeson.Encoding as A (value, fromEncoding)+-- alga+import qualified Algebra.Graph as G (Graph(..), edges, foldg)+import qualified Algebra.Graph.Labelled as GL (Graph(..), edges, foldg)++-- unlabeled edges++instance A.ToJSON a => A.ToJSON (G.Graph a) where+ toJSON = graphToValue+++graphToValue :: (A.ToJSON t) =>+ G.Graph t -> A.Value+graphToValue = go+ where+ go G.Empty = A.toJSON Empty+ go (G.Vertex x) = A.toJSON (Vertex x)+ go (G.Overlay x y) = A.toJSON (Overlay (go x) (go y))+ go (G.Connect x y) = A.toJSON (Connect (go x) (go y))+++++instance A.FromJSON a => A.FromJSON (G.Graph a) where+ parseJSON x = A.withObject "Graph" gObj x <|>+ parseE x++gObj :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)+gObj o = parseC o <|>+ parseO o <|>+ parseV o++parseE :: A.Value -> A.Parser (G.Graph a)+parseE = A.withArray "empty" $ \t -> if null t then pure G.Empty else fail "cannot parse Empty"++parseV :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)+parseV o = G.Vertex <$> o A..: "v"++parseO :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)+parseO o = do+ a <- o A..: "o1"+ b <- o A..: "o2"+ pure $ G.Overlay a b++parseC :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)+parseC o = do+ a <- o A..: "c1"+ b <- o A..: "c2"+ pure $ G.Connect a b+++++instance (A.ToJSON a, A.ToJSON e) => A.ToJSON (GL.Graph e a) where+ toJSON = graphLToValue++graphLToValue :: (A.ToJSON a, A.ToJSON e) => GL.Graph e a -> A.Value+graphLToValue = go+ where+ go GL.Empty = A.toJSON Empty+ go (GL.Vertex x) = A.toJSON (Vertex x)+ go (GL.Connect e x y) = A.toJSON (LEdge e (go x) (go y))+++instance (A.FromJSON e, A.FromJSON a) => A.FromJSON (GL.Graph e a) where+ parseJSON x = A.withObject "Graph (labeled)" gLObj x <|>+ parseEL x++gLObj :: (A.FromJSON e, A.FromJSON a) => A.Object -> A.Parser (GL.Graph e a)+gLObj o = parseCL o <|>+ parseVL o++parseEL :: A.Value -> A.Parser (GL.Graph e a)+parseEL = A.withArray "empty" $ \t -> if null t then pure GL.Empty else fail "cannot parse Empty"++parseVL :: A.FromJSON a => A.Object -> A.Parser (GL.Graph e a)+parseVL o = GL.Vertex <$> o A..: "v"++parseCL :: (A.FromJSON e, A.FromJSON a) =>+ A.Object -> A.Parser (GL.Graph e a)+parseCL o = do+ e <- o A..: "l"+ a <- o A..: "e1"+ b <- o A..: "e2"+ pure $ GL.Connect e a b+++-- | Helper types++-- empty+data Empty = Empty deriving (Eq, Show, Generic)+instance A.ToJSON Empty+-- vertex+newtype Vertex a = Vertex { v :: a } deriving (Eq, Show, Generic)+instance A.ToJSON a => A.ToJSON (Vertex a)++-- overlay+data Overlay a = Overlay { o1 :: a, o2 :: a} deriving (Eq, Show, Generic)+instance A.ToJSON a => A.ToJSON (Overlay a)++-- connect+data Connect a = Connect { c1 :: a, c2 :: a} deriving (Eq, Show, Generic)+instance A.ToJSON a => A.ToJSON (Connect a)+++++data LEdge e a = LEdge { l :: e, e1 :: a, e2 :: a } deriving (Eq, Show, Generic)+instance (A.ToJSON e, A.ToJSON a) => A.ToJSON (LEdge e a)+
− src/Algebra/Graph/IO/MatrixMarket.hs
@@ -1,4 +0,0 @@-{-# options_ghc -Wno-unused-imports #-}-module Algebra.Graph.IO.MatrixMarket where--import Data.Matrix.MatrixMarket (Matrix(..), readMatrix', nnz, dim, numDat, Array(..), readArray', dimArr, numDatArr, Structure(..), ImportError(..))
+ src/Algebra/Graph/IO/Serialise.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-|+Module : Algebra.Graph.IO.Serialise+Description : 'serialise' instances for algebraic-graphs types+Copyright : (c) Marco Zocca, 2022+Maintainer : ocramz+Stability : experimental+Portability : POSIX++Orphan instances for compatibility between 'algebraic-graphs' and 'serialise'.++Import only if you know what you're doing.+-}+module Algebra.Graph.IO.Serialise () where++-- alga+import qualified Algebra.Graph as G (Graph(..), edges, foldg)+import qualified Algebra.Graph.Labelled as GL (Graph(..), edges, foldg)+-- serialise+import qualified Codec.Serialise as CS (Serialise(..), serialise, serialiseIncremental, deserialiseOrFail, DeserialiseFailure)+import qualified Codec.Serialise.Encoding as CS (encodeListLen, encodeListLenIndef, encodeWord)+import qualified Codec.Serialise.Decoding as CS (decodeListLen, decodeListLenIndef, decodeWord)+++instance CS.Serialise a => CS.Serialise (G.Graph a) where+ encode = \case+ G.Empty -> CS.encodeListLen 1 <> CS.encodeWord 0+ G.Vertex x -> CS.encodeListLen 2 <> CS.encodeWord 1 <> CS.encode x+ G.Overlay a b -> CS.encodeListLen 3 <> CS.encodeWord 2 <> CS.encode a <> CS.encode b+ G.Connect a b -> CS.encodeListLen 3 <> CS.encodeWord 3 <> CS.encode a <> CS.encode b+ decode = do+ n <- CS.decodeListLen+ t <- CS.decodeWord -- constructor tag+ case (t, n) of+ (0, 1) -> pure $ G.Empty+ (1, 2) -> do+ !x <- CS.decode+ pure $ G.Vertex x+ (2, 3) -> do+ !x <- CS.decode+ !y <- CS.decode+ pure $ G.Overlay x y+ (3, 3) -> do+ !x <- CS.decode+ !y <- CS.decode+ pure $ G.Connect x y+ e -> fail $ unwords ["unknown tag", show e]++instance (CS.Serialise e, CS.Serialise a) => CS.Serialise (GL.Graph e a) where+ encode = \case+ GL.Empty -> CS.encodeListLen 1 <> CS.encodeWord 0+ GL.Vertex x -> CS.encodeListLen 2 <> CS.encodeWord 1 <> CS.encode x+ GL.Connect e a b -> CS.encodeListLen 4 <> CS.encodeWord 2 <> CS.encode e <> CS.encode a <> CS.encode b+ decode = do+ n <- CS.decodeListLen+ t <- CS.decodeWord -- constructor tag+ case (t, n) of+ (0, 1) -> pure $ GL.Empty+ (1, 2) -> do+ !x <- CS.decode+ pure $ GL.Vertex x+ (2, 4) -> do+ !e <- CS.decode+ !x <- CS.decode+ !y <- CS.decode+ pure $ GL.Connect e x y+ e -> fail $ unwords ["unknown tag", show e]