packages feed

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 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]