packages feed

souffle-haskell 0.2.2 → 0.2.3

raw patch · 5 files changed

+98/−140 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Language.Souffle.Compiled: instance (Control.Monad.Writer.Class.MonadWriter w m, Control.Monad.State.Class.MonadState s m) => Control.Monad.RWS.Class.MonadRWS Language.Souffle.Compiled.Tuple w s (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance Control.Monad.Trans.Class.MonadTrans Language.Souffle.Compiled.MarshalT
- Language.Souffle.Compiled: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance GHC.Base.Applicative m => GHC.Base.Applicative (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Language.Souffle.Compiled.Tuple (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Compiled: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Souffle.Compiled.MarshalT m)
- Language.Souffle.Marshal: PopInt :: (Int32 -> a) -> PopF a
- Language.Souffle.Marshal: PopStr :: (String -> a) -> PopF a
- Language.Souffle.Marshal: PushInt :: Int32 -> a -> PushF a
- Language.Souffle.Marshal: PushStr :: String -> a -> PushF a
- Language.Souffle.Marshal: data MarshalM f a
- Language.Souffle.Marshal: data PopF a
- Language.Souffle.Marshal: data PushF a
- Language.Souffle.Marshal: instance GHC.Base.Functor Language.Souffle.Marshal.PopF
- Language.Souffle.Marshal: instance GHC.Base.Functor Language.Souffle.Marshal.PushF
- Language.Souffle.Marshal: instance GHC.Base.Functor f => GHC.Base.Applicative (Language.Souffle.Marshal.MarshalM f)
- Language.Souffle.Marshal: instance GHC.Base.Functor f => GHC.Base.Functor (Language.Souffle.Marshal.MarshalM f)
- Language.Souffle.Marshal: instance GHC.Base.Functor f => GHC.Base.Monad (Language.Souffle.Marshal.MarshalM f)
- Language.Souffle.Marshal: interpret :: Monad m => (forall x. f x -> m x) -> MarshalM f a -> m a
+ Language.Souffle.Compiled: instance Control.Monad.IO.Class.MonadIO Language.Souffle.Compiled.CMarshal
+ Language.Souffle.Compiled: instance Control.Monad.Reader.Class.MonadReader Language.Souffle.Compiled.Tuple Language.Souffle.Compiled.CMarshal
+ Language.Souffle.Compiled: instance GHC.Base.Applicative Language.Souffle.Compiled.CMarshal
+ Language.Souffle.Compiled: instance GHC.Base.Functor Language.Souffle.Compiled.CMarshal
+ Language.Souffle.Compiled: instance GHC.Base.Monad Language.Souffle.Compiled.CMarshal
+ Language.Souffle.Compiled: instance Language.Souffle.Marshal.MonadPop Language.Souffle.Compiled.CMarshal
+ Language.Souffle.Compiled: instance Language.Souffle.Marshal.MonadPush Language.Souffle.Compiled.CMarshal
+ Language.Souffle.Interpreted: instance Language.Souffle.Marshal.MonadPop Language.Souffle.Interpreted.IMarshal
+ Language.Souffle.Interpreted: instance Language.Souffle.Marshal.MonadPush Language.Souffle.Interpreted.IMarshal
+ Language.Souffle.Marshal: class Monad m => MonadPop m
+ Language.Souffle.Marshal: class Monad m => MonadPush m
+ Language.Souffle.Marshal: popInt :: MonadPop m => m Int32
+ Language.Souffle.Marshal: popString :: MonadPop m => m String
+ Language.Souffle.Marshal: pushInt :: MonadPush m => Int32 -> m ()
+ Language.Souffle.Marshal: pushString :: MonadPush m => String -> m ()
- Language.Souffle.Compiled: pop :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a)) => MarshalM PopF a
+ Language.Souffle.Compiled: pop :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a), MonadPop m) => m a
- Language.Souffle.Compiled: push :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a)) => a -> MarshalM PushF ()
+ Language.Souffle.Compiled: push :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a), MonadPush m) => a -> m ()
- Language.Souffle.Interpreted: pop :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a)) => MarshalM PopF a
+ Language.Souffle.Interpreted: pop :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a), MonadPop m) => m a
- Language.Souffle.Interpreted: push :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a)) => a -> MarshalM PushF ()
+ Language.Souffle.Interpreted: push :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a), MonadPush m) => a -> m ()
- Language.Souffle.Marshal: pop :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a)) => MarshalM PopF a
+ Language.Souffle.Marshal: pop :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a), MonadPop m) => m a
- Language.Souffle.Marshal: push :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a)) => a -> MarshalM PushF ()
+ Language.Souffle.Marshal: push :: (Marshal a, Generic a, SimpleProduct a (Rep a), GMarshal (Rep a), MonadPush m) => a -> m ()

Files

CHANGELOG.md view
@@ -4,6 +4,12 @@ All notable changes to this project (as seen by library users) will be documented in this file. The CHANGELOG is available on [Github](https://github.com/luc-tielen/souffle-haskell.git/CHANGELOG.md). +## [0.2.2] - 2020-05-21+### Changed++- Optimize performance when marshalling and unmarshalling facts.++ ## [0.2.2] - 2020-04-30 ### Changed 
lib/Language/Souffle/Compiled.hs view
@@ -1,6 +1,5 @@ {-# OPTIONS_GHC -Wno-redundant-constraints #-}-{-# LANGUAGE TypeFamilies, TypeOperators, DerivingVia, InstanceSigs, BangPatterns #-}-{-# LANGUAGE DataKinds, FlexibleContexts #-}+{-# LANGUAGE TypeFamilies, DerivingVia, InstanceSigs, BangPatterns #-}  -- | This module provides an implementation for the typeclasses defined in --   "Language.Souffle.Class".@@ -50,46 +49,37 @@  type Tuple = Ptr Internal.Tuple --- | A monad transformer, used solely for marshalling and unmarshalling+-- | A monad used solely for marshalling and unmarshalling --   between Haskell and Souffle Datalog.-newtype MarshalT m a = MarshalT (ReaderT Tuple m a)-  deriving ( Functor, Applicative, Monad-           , MonadIO, MonadReader Tuple, MonadWriter w-           , MonadState s, MonadRWS Tuple w s, MonadError e )-  via ( ReaderT Tuple m )-  deriving MonadTrans via (ReaderT Tuple)+newtype CMarshal a = CMarshal (ReaderT Tuple IO a)+  deriving (Functor, Applicative, Monad, MonadIO, MonadReader Tuple)+  via ( ReaderT Tuple IO ) -runM :: Monad m => MarshalT m a -> Tuple -> m a-runM (MarshalT m) = runReaderT m+runM :: CMarshal a -> Tuple -> IO a+runM (CMarshal m) = runReaderT m {-# INLINABLE runM #-} --- | Execute the monad transformer and return the result.---   The tuple that is passed in will be used to marshal the data back and forth.-runPushT :: MonadIO m => MarshalM PushF a -> Tuple -> m a-runPushT = runM . interpret pushAlgM where-  pushAlgM (PushInt int v) = do+instance MonadPush CMarshal where+  pushInt int = do     tuple <- ask     liftIO $ Internal.tuplePushInt tuple int-    pure v-  pushAlgM (PushStr str v) = do+  {-# INLINABLE pushInt #-}++  pushString str = do     tuple <- ask     liftIO $ Internal.tuplePushString tuple str-    pure v-{-# INLINABLE runPushT #-}+  {-# INLINABLE pushString #-} --- | Execute the monad transformer and return the result.---   The tuple that is passed in will be used to marshal the data back and forth.-runPopT :: MonadIO m => MarshalM PopF a -> Tuple -> m a-runPopT = runM . interpret popAlgM where-  popAlgM (PopStr f) = MarshalT $ do+instance MonadPop CMarshal where+  popInt = do     tuple <- ask-    str   <- liftIO $ Internal.tuplePopString tuple-    pure $ f str-  popAlgM (PopInt f) = MarshalT $ do+    liftIO $ Internal.tuplePopInt tuple+  {-# INLINABLE popInt #-}++  popString = do     tuple <- ask-    int   <- liftIO $ Internal.tuplePopInt tuple-    pure $ f int-{-# INLINABLE runPopT #-}+    liftIO $ Internal.tuplePopString tuple+  {-# INLINABLE popString #-}  class Collect c where   collect :: Marshal a => Int -> ForeignPtr Internal.RelationIterator -> IO (c a)@@ -100,7 +90,7 @@       go idx count acc _ | idx == count = pure acc       go idx count !acc !it = do         tuple <- Internal.relationIteratorNext it-        result <- runPopT pop tuple+        result <- runM pop tuple         go (idx + 1) count (result : acc) it   {-# INLINABLE collect #-} @@ -112,7 +102,7 @@       go vec idx count _ | idx == count = V.unsafeFreeze vec       go vec idx count it = do         tuple <- Internal.relationIteratorNext it-        result <- runPopT pop tuple+        result <- runM pop tuple         MV.unsafeWrite vec idx result         go vec (idx + 1) count it   {-# INLINABLE collect #-}@@ -166,19 +156,19 @@    findFact :: forall a prog. (Fact a, ContainsFact prog a)            => Handle prog -> a -> SouffleM (Maybe a)-  findFact (Handle prog) a = SouffleM $ do+  findFact (Handle prog) fact = SouffleM $ do     let relationName = factName (Proxy :: Proxy a)     relation <- Internal.getRelation prog relationName     tuple <- Internal.allocTuple relation-    withForeignPtr tuple $ runPushT (push a)+    withForeignPtr tuple $ runM (push fact)     found <- Internal.containsTuple relation tuple-    pure $ if found then Just a else Nothing+    pure $ if found then Just fact else Nothing   {-# INLINABLE findFact #-}  addFact' :: Fact a => Ptr Internal.Relation -> a -> IO () addFact' relation fact = do   tuple <- Internal.allocTuple relation-  withForeignPtr tuple $ runPushT (push fact)+  withForeignPtr tuple $ runM (push fact)   Internal.addTuple relation tuple {-# INLINABLE addFact' #-} 
lib/Language/Souffle/Interpreted.hs view
@@ -1,5 +1,5 @@ {-# OPTIONS_GHC -Wno-redundant-constraints #-}-{-# LANGUAGE DataKinds, FlexibleContexts, TypeFamilies, DerivingVia, InstanceSigs #-}+{-# LANGUAGE TypeFamilies, DerivingVia, InstanceSigs #-}  -- | This module provides an implementation for the `MonadSouffle` typeclass --   defined in "Language.Souffle.Class".@@ -118,40 +118,34 @@   }  newtype IMarshal a = IMarshal (State [String] a)-  deriving-    ( Functor-    , Applicative-    , Monad-    , MonadState [String]-    )+  deriving (Functor, Applicative, Monad, MonadState [String])   via (State [String]) -popMarshalT :: MarshalM PopF a -> [String] -> a-popMarshalT = runM . interpret popAlgM where-  runM (IMarshal m) = evalState m-  popAlgM (PopStr f) = do-    str <- state (\case-              [] -> error "Empty fact stack"-              (h:t) -> (h, t))-    pure $ f str-  popAlgM (PopInt f) = do-    int <- state (\case-              [] -> error "Empty fact stack"-              (h:t) -> (read h, t))-    pure $ f int+instance MonadPush IMarshal where+  pushInt int = modify (show int:)+  {-# INLINABLE pushInt #-}++  pushString str = modify (str:)+  {-# INLINABLE pushString #-}++instance MonadPop IMarshal where+  popInt = state $ \case+    [] -> error "Empty fact stack"+    (h:t) -> (read h, t)+  {-# INLINABLE popInt #-}++  popString = state $ \case+    [] -> error "Empty fact stack"+    (h:t) -> (h, t)+  {-# INLINABLE popString #-}++popMarshalT :: IMarshal a -> [String] -> a+popMarshalT (IMarshal m) = evalState m {-# INLINABLE popMarshalT #-} -pushMarshalT :: MarshalM PushF a -> [String]-pushMarshalT = runM . interpret pushAlgM where-  runM (IMarshal m) = reverse $ execState m []-  pushAlgM (PushInt i v) = do-    modify (show i:)-    pure v-  pushAlgM (PushStr s v) = do-    modify (s:)-    pure v+pushMarshalT :: IMarshal a -> [String]+pushMarshalT (IMarshal m) = reverse $ execState m [] {-# INLINABLE pushMarshalT #-}-  class Collect c where   collect :: Marshal a => FilePath -> IO (c a)
lib/Language/Souffle/Marshal.hs view
@@ -1,18 +1,15 @@ {-# OPTIONS_GHC -Wno-redundant-constraints #-}-{-# LANGUAGE FlexibleInstances, FlexibleContexts, DeriveFunctor #-}-{-# LANGUAGE DefaultSignatures, TypeOperators, RankNTypes #-}+{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}+{-# LANGUAGE DefaultSignatures, TypeOperators #-}  -- | This module exposes a uniform interface to marshal values---   to and from Souffle Datalog. This is done via the 'Marshal' typeclass---   and 'MarshalM' monad.+--   to and from Souffle Datalog. This is done via the 'Marshal' typeclass. --   Also, a mechanism is exposed for generically deriving marshalling --   and unmarshalling code for simple product types. module Language.Souffle.Marshal   ( Marshal(..)-  , PushF(..)-  , PopF(..)-  , MarshalM-  , interpret+  , MonadPush(..)+  , MonadPop(..)   ) where  import GHC.Generics@@ -21,56 +18,29 @@ import qualified Data.Text.Lazy as TL import qualified Language.Souffle.Internal.Constraints as C ---- | A data type used for deserializing a `Marshal`-able value---   from Souffle to Haskell, only used internally.-data PopF a-  = PopInt (Int32 -> a)-  | PopStr (String -> a)-  deriving Functor---- | A data type used for serializing a `Marshal`-able value---   from Haskell to Souffle, only used internally.-data PushF a-  = PushInt Int32 a-  | PushStr String a-  deriving Functor---- NOTE: Free is reimplemented here to avoid pulling in quite a few---       dependencies and since we only need 2 functions+{- | A typeclass for serializing primitive values from Haskell to Datalog. --- | The monad used for serializing and deserializing of values that---   implement the `Marshal` typeclass.-data MarshalM f a-  = Pure a-  | Free (f (MarshalM f a))-  deriving Functor+This typeclass is only used internally and subject to change. -instance Functor f => Applicative (MarshalM f) where-  pure = Pure-  {-# INLINABLE pure #-}-  Pure f <*> Pure a = Pure $ f a-  Pure f <*> Free fa = f <$> Free fa-  Free fa <*> m = Free $ fmap (<*> m) fa-  {-# INLINABLE (<*>) #-}+See also: 'MonadPop', 'Marshal'.+-}+class Monad m => MonadPush m where+  -- | Marshals an integer to the datalog side.+  pushInt :: Int32 -> m ()+  -- | Marshals a string to the datalog side.+  pushString :: String -> m () -instance Functor f => Monad (MarshalM f) where-  Pure a >>= f = f a-  Free fa >>= f = Free $ fmap (>>= f) fa-  {-# INLINABLE (>>=) #-}+{- | A typeclass for serializing primitive values from Datalog to Haskell. -liftF :: Functor f => f a -> MarshalM f a-liftF action = Free $ fmap pure action-{-# INLINABLE liftF #-}+This typeclass is only used internally and subject to change. --- | Helper function for interpreting the actual (de-)serialization of values.---   This allows both the compiled and interpreted variant to handle---   (de-)serialization in their own way.-interpret :: Monad m => (forall x. f x -> m x) -> MarshalM f a -> m a-interpret f = \case-  Pure a -> pure a-  Free fa -> f fa >>= interpret f-{-# INLINABLE interpret #-}+See also: 'MonadPush', 'Marshal'.+-}+class Monad m => MonadPop m where+  -- | Unmarshals an integer from the datalog side.+  popInt :: m Int32+  -- | Unmarshals a string from the datalog side.+  popString :: m String  {- | A typeclass for providing a uniform API to marshal/unmarshal values      between Haskell and Souffle datalog.@@ -93,46 +63,48 @@ -} class Marshal a where   -- | Marshals a value to the datalog side.-  push :: a -> MarshalM PushF ()+  push :: MonadPush m => a -> m ()   -- | Unmarshals a value from the datalog side.-  pop :: MarshalM PopF a+  pop :: MonadPop m => m a -  default push :: (Generic a, C.SimpleProduct a (Rep a), GMarshal (Rep a))-               => a -> MarshalM PushF ()-  default pop :: (Generic a, C.SimpleProduct a (Rep a), GMarshal (Rep a))-              => MarshalM PopF a+  default push+    :: (Generic a, C.SimpleProduct a (Rep a), GMarshal (Rep a), MonadPush m)+    => a -> m ()+  default pop+    :: (Generic a, C.SimpleProduct a (Rep a), GMarshal (Rep a), MonadPop m)+    => m a   push a = gpush (from a)   {-# INLINABLE push #-}   pop = to <$> gpop   {-# INLINABLE pop #-}  instance Marshal Int32 where-  push int = liftF (PushInt int ())+  push = pushInt   {-# INLINABLE push #-}-  pop  = liftF (PopInt id)+  pop = popInt   {-# INLINABLE pop #-}  instance Marshal String where-  push str = liftF (PushStr str ())+  push = pushString   {-# INLINABLE push #-}-  pop  = liftF (PopStr id)+  pop = popString   {-# INLINABLE pop #-}  instance Marshal T.Text where   push = push . T.unpack   {-# INLINABLE push #-}-  pop  = T.pack <$> pop+  pop = T.pack <$> pop   {-# INLINABLE pop #-}  instance Marshal TL.Text where   push = push . TL.unpack   {-# INLINABLE push #-}-  pop  = TL.pack <$> pop+  pop = TL.pack <$> pop   {-# INLINABLE pop #-}  class GMarshal f where-  gpush :: f a -> MarshalM PushF ()-  gpop  :: MarshalM PopF (f a)+  gpush :: MonadPush m => f a -> m ()+  gpop  :: MonadPop m => m (f a)  instance Marshal a => GMarshal (K1 i a) where   gpush (K1 x) = push x
souffle-haskell.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 25ea3b610616a6824b69546c184f2e1fd2cdcb36e648715c6166441f27013011+-- hash: edee24fd0c26174211bf0f36205df0d361d3a2d6d55987259a09e4b4a80bd62d  name:           souffle-haskell-version:        0.2.2+version:        0.2.3 synopsis:       Souffle Datalog bindings for Haskell description:    Souffle Datalog bindings for Haskell. category:       Logic Programming, Foreign Binding, Bindings@@ -68,8 +68,6 @@     extra-libraries:         stdc++   default-language: Haskell2010-  build-tools:-      souffle  test-suite souffle-haskell-test   type: exitcode-stdio-1.0@@ -84,8 +82,6 @@   default-extensions: OverloadedStrings LambdaCase ScopedTypeVariables   ghc-options: -Wall -Weverything -Wno-safe -Wno-unsafe -Wno-implicit-prelude -Wno-missed-specializations -Wno-all-missed-specializations -Wno-missing-import-lists -Wno-type-defaults -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-missing-deriving-strategies -optP-Wno-nonportable-include-path -fhide-source-paths -fno-show-valid-hole-fits -fno-sort-valid-hole-fits   cpp-options: -std=c++17 -D__EMBEDDED_SOUFFLE__-  build-tools:-      souffle   build-depends:       base >=4.12 && <5     , deepseq >=1.4.4 && <2