{-# LANGUAGE DataKinds, UndecidableInstances, FlexibleContexts #-}
{-# LANGUAGE TypeFamilies, TypeOperators, TypeApplications #-}

-- | This module provides the top level API for Souffle related operations.
--   It makes use of Haskell's powerful typesystem to make certain invalid states
--   impossible to represent. It does this with a small type level DSL for
--   describing properties of the Datalog program (see the 'Program' and 'Fact'
--   typeclasses for more information).
--
--   The Souffle operations are exposed via 2 mtl-style interfaces
--   (see `MonadSouffle` and `MonadSouffleFileIO`) that allows them to be
--   integrated with existing monad transformer stacks.
--
--   This module also contains some helper type families for additional
--   type safety and user-friendly error messages.
module Language.Souffle.Class
  ( Program(..)
  , ProgramOptions(..)
  , Fact(..)
  , FactOptions(..)
  , Marshal.Marshal(..)
  , Direction(..)
  , ContainsInputFact
  , ContainsOutputFact
  , ContainsFact
  , MonadSouffle(..)
  , MonadSouffleFileIO(..)
  ) where

import Prelude hiding ( init )

import Control.Monad.Except
import Control.Monad.Reader
import Control.Monad.Writer
import qualified Control.Monad.RWS.Strict as StrictRWS
import qualified Control.Monad.RWS.Lazy as LazyRWS
import qualified Control.Monad.State.Strict as StrictState
import qualified Control.Monad.State.Lazy as LazyState
import Data.Proxy
import Data.Kind
import Data.Word
import GHC.TypeLits
import qualified Language.Souffle.Marshal as Marshal


-- | A helper type family for checking if a specific Souffle `Program` contains
--   a certain `Fact`. Additionally, it also checks if the fact is marked as
--   either `Input` or `InputOutput`. This constraint will generate a
--   user-friendly type error if these conditions are not met.
type ContainsInputFact :: Type -> Type -> Constraint
type family ContainsInputFact prog fact where
  ContainsInputFact prog fact = (ContainsFact prog fact, IsInput fact (FactDirection fact))

-- | A helper type family for checking if a specific Souffle `Program` contains
--   a certain `Fact`. Additionally, it also checks if the fact is marked as
--   either `Output` or `InputOutput`. This constraint will generate a
--   user-friendly type error if these conditions are not met.
type ContainsOutputFact :: Type -> Type -> Constraint
type family ContainsOutputFact prog fact where
  ContainsOutputFact prog fact = (ContainsFact prog fact, IsOutput fact (FactDirection fact))

type IsInput :: Type -> Direction -> Constraint
type family IsInput fact dir where
  IsInput _ 'Input = ()
  IsInput _ 'InputOutput = ()
  IsInput fact dir = TypeError
    ( 'Text "You tried to use an " ':<>: 'ShowType (FormatDirection dir) ':<>: 'Text " fact of type " ':<>: 'ShowType fact ':<>: 'Text " as an input."
    ':$$: 'Text "Possible solution: change the FactDirection of " ':<>: 'ShowType fact
      ':<>: 'Text " to either 'Input' or 'InputOutput'."
    )

type IsOutput :: Type -> Direction -> Constraint
type family IsOutput fact dir where
  IsOutput _ 'Output = ()
  IsOutput _ 'InputOutput = ()
  IsOutput fact dir = TypeError
    ( 'Text "You tried to use an " ':<>: 'ShowType (FormatDirection dir) ':<>: 'Text " fact of type " ':<>: 'ShowType fact ':<>: 'Text " as an output."
    ':$$: 'Text "Possible solution: change the FactDirection of " ':<>: 'ShowType fact
      ':<>: 'Text " to either 'Output' or 'InputOutput'."
    )

type FormatDirection :: Direction -> Symbol
type family FormatDirection dir where
  FormatDirection 'Output = "output"
  FormatDirection 'Input = "input"
  FormatDirection 'Internal = "internal"

-- | A helper type family for checking if a specific Souffle `Program` contains
--   a certain `Fact`. This constraint will generate a user-friendly type error
--   if this is not the case.
type ContainsFact :: Type -> Type -> Constraint
type family ContainsFact prog fact where
  ContainsFact prog fact =
    CheckContains prog (ProgramFacts prog) fact

type CheckContains :: Type -> [Type] -> Type -> Constraint
type family CheckContains prog facts fact :: Constraint where
  CheckContains prog '[] fact =
    TypeError ('Text "You tried to perform an action with a fact of type '" ':<>: 'ShowType fact
    ':<>: 'Text "' for program '" ':<>: 'ShowType prog ':<>: 'Text "'."
    ':$$: 'Text "The program contains the following facts: " ':<>: 'ShowType (ProgramFacts prog) ':<>: 'Text "."
    ':$$: 'Text "It does not contain fact: " ':<>: 'ShowType fact ':<>: 'Text "."
    ':$$: 'Text "You can fix this error by adding the type '" ':<>: 'ShowType fact
    ':<>: 'Text "' to the ProgramFacts type in the Program instance for " ':<>: 'ShowType prog ':<>: 'Text ".")
  CheckContains _ (a ': _) a = ()
  CheckContains prog (_ ': as) b = CheckContains prog as b

-- | A typeclass for describing a datalog program.
--
-- Example usage (assuming the program was generated from path.dl
-- and contains 2 facts: Edge and Reachable):
--
-- @
-- data Path = Path  -- Handle for the datalog program
--
-- instance Program Path where
--   type ProgramFacts Path = '[Edge, Reachable]
--   programName = const "path"
-- @
type Program :: Type -> Constraint
class Program a where
  -- | A type level list of facts that belong to this program.
  --   This list is used to check that only known facts are added to a program.
  type ProgramFacts a :: [Type]

  -- | Function for obtaining the name of a Datalog program.
  --   This has to be the same as the name of the .dl file (minus the extension).
  programName :: a -> String

-- | A helper data type, used in combination with the DerivingVia extension to
--   automatically generate code to bind Haskell to a Souffle Datalog program.
--
-- The following is an example how to bind to a Datalog program "path"
-- (saved as path.dl / path.cpp), that uses two facts called "edge" and
-- "reachable" (represented with the Edge and Reachable types):
--
-- @
-- data Path = Path
--   deriving Souffle.Program
--   via Souffle.ProgramOptions Path "path" '[Edge, Reachable]
-- @
--
-- See also: 'FactOptions'.
type ProgramOptions :: Type -> Symbol -> [Type] -> Type
newtype ProgramOptions prog progName facts
  = ProgramOptions prog

instance KnownSymbol progName => Program (ProgramOptions prog progName facts) where
  type ProgramFacts (ProgramOptions _ _ facts) = facts

  programName :: ProgramOptions prog progName facts -> String
programName = String -> ProgramOptions prog progName facts -> String
forall a b. a -> b -> a
const (String -> ProgramOptions prog progName facts -> String)
-> String -> ProgramOptions prog progName facts -> String
forall a b. (a -> b) -> a -> b
$ Proxy progName -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy progName
forall k (t :: k). Proxy t
Proxy @progName)
  {-# INLINABLE programName #-}

-- | A typeclass for data types representing a fact in datalog.
--
-- Example usage:
--
-- @
-- instance Fact Edge where
--   type FactDirection Edge = 'Input
--   factName = const "edge"
-- @
type Fact :: Type -> Constraint
class Marshal.Marshal a => Fact a where
  -- | The direction or "mode" a fact can be used in.
  --   This is used to perform compile-time checks that a fact is only used
  --   in valid situations. For more information, see the 'Direction' type.
  type FactDirection a :: Direction

  -- | Function for obtaining the name of a fact
  --   (has to be the same as described in the Datalog program).
  --
  -- It uses a 'Proxy' to select the correct instance.
  factName :: Proxy a -> String

-- | A helper data type, used in combination with the DerivingVia extension to
--   automatically generate code to bind a Haskell datatype to a Souffle
--   Datalog fact.
--
-- The following is an example how to bind to a Datalog fact "edge"
-- that contains two symbols (strings in Haskell) that is an input (from the
-- Datalog point of view):
--
-- @
-- data Edge = Edge String String
--   deriving (Eq, Show, Generic)
--   deriving anyclass Souffle.Marshal
--   deriving Souffle.Fact
--   via Souffle.FactOptions Edge "edge" 'Souffle.Input
-- @
--
-- See also: 'ProgramOptions'.
type FactOptions :: Type -> Symbol -> Direction -> Type
newtype FactOptions fact factName dir
  = FactOptions fact

instance Marshal.Marshal fact => Marshal.Marshal (FactOptions fact name dir) where
  push :: FactOptions fact name dir -> m ()
push (FactOptions fact
fact) = fact -> m ()
forall a (m :: * -> *). (Marshal a, MonadPush m) => a -> m ()
Marshal.push fact
fact
  {-# INLINABLE push #-}
  pop :: m (FactOptions fact name dir)
pop = fact -> FactOptions fact name dir
forall fact (factName :: Symbol) (dir :: Direction).
fact -> FactOptions fact factName dir
FactOptions (fact -> FactOptions fact name dir)
-> m fact -> m (FactOptions fact name dir)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m fact
forall a (m :: * -> *). (Marshal a, MonadPop m) => m a
Marshal.pop
  {-# INLINABLE pop #-}

instance ( Marshal.Marshal fact
         , KnownSymbol factName
         ) => Fact (FactOptions fact factName dir) where
  type FactDirection (FactOptions _ _ dir) = dir

  factName :: Proxy (FactOptions fact factName dir) -> String
factName = String -> Proxy (FactOptions fact factName dir) -> String
forall a b. a -> b -> a
const (String -> Proxy (FactOptions fact factName dir) -> String)
-> String -> Proxy (FactOptions fact factName dir) -> String
forall a b. (a -> b) -> a -> b
$ Proxy factName -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy factName
forall k (t :: k). Proxy t
Proxy @factName)
  {-# INLINABLE factName #-}


-- | A datatype describing which operations a certain fact supports.
--   The direction is from the datalog perspective, so that it
--   aligns with ".decl" statements in Souffle.
type Direction :: Type
data Direction
  = Input
  -- ^ Fact can only be stored in Datalog (using `addFact`/`addFacts`).
  | Output
  -- ^ Fact can only be read from Datalog (using `getFacts`/`findFact`).
  | InputOutput
  -- ^ Fact supports both reading from / writing to Datalog.
  | Internal
  -- ^ Supports neither reading from / writing to Datalog. This is used for
  --   facts that are only visible inside Datalog itself.

-- | A mtl-style typeclass for Souffle-related actions.
type MonadSouffle :: (Type -> Type) -> Constraint
class Monad m => MonadSouffle m where
  -- | Represents a handle for interacting with a Souffle program.
  --
  --   The handle is used in all other functions of this typeclass to perform
  --   Souffle-related actions.
  type Handler m :: Type -> Type

  -- | Helper associated type constraint that allows collecting facts from
  --   Souffle in a list or vector. Only used internally.
  type CollectFacts m (c :: Type -> Type) :: Constraint
  -- | Helper associated type constraint that allows submitting facts to
  --   Souffle. Only used internally.
  type SubmitFacts m (a :: Type) :: Constraint

  -- | Runs the Souffle program.
  run :: Handler m prog -> m ()

  -- | Sets the number of CPU cores this Souffle program should use.
  setNumThreads :: Handler m prog -> Word64 -> m ()

  -- | Gets the number of CPU cores this Souffle program should use.
  getNumThreads :: Handler m prog -> m Word64

  -- | Returns all facts of a program. This function makes use of type inference
  --   to select the type of fact to return.
  getFacts :: (Fact a, ContainsOutputFact prog a, CollectFacts m c)
           => Handler m prog -> m (c a)

  -- | Searches for a fact in a program.
  --   Returns 'Nothing' if no matching fact was found; otherwise 'Just' the fact.
  --
  --   Conceptually equivalent to @List.find (== fact) \<$\> getFacts prog@,
  --   but this operation can be implemented much faster.
  findFact :: (Fact a, ContainsOutputFact prog a, Eq a, SubmitFacts m a)
           => Handler m prog -> a -> m (Maybe a)

  -- | Adds a fact to the program.
  addFact :: (Fact a, ContainsInputFact prog a, SubmitFacts m a)
          => Handler m prog -> a -> m ()

  -- | Adds multiple facts to the program. This function could be implemented
  --   in terms of 'addFact', but this is done as a minor optimization.
  addFacts :: (Foldable t, Fact a, ContainsInputFact prog a, SubmitFacts m a)
           => Handler m prog -> t a -> m ()

instance MonadSouffle m => MonadSouffle (ReaderT r m) where
  type Handler (ReaderT r m) = Handler m
  type CollectFacts (ReaderT r m) c = CollectFacts m c
  type SubmitFacts (ReaderT r m) a = SubmitFacts m a

  run :: Handler (ReaderT r m) prog -> ReaderT r m ()
run = m () -> ReaderT r m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT r m ())
-> (Handler m prog -> m ()) -> Handler m prog -> ReaderT r m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m ()
forall (m :: * -> *) prog. MonadSouffle m => Handler m prog -> m ()
run
  {-# INLINABLE run #-}
  setNumThreads :: Handler (ReaderT r m) prog -> Word64 -> ReaderT r m ()
setNumThreads Handler (ReaderT r m) prog
prog = m () -> ReaderT r m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT r m ())
-> (Word64 -> m ()) -> Word64 -> ReaderT r m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> Word64 -> m ()
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> Word64 -> m ()
setNumThreads Handler m prog
Handler (ReaderT r m) prog
prog
  {-# INLINABLE setNumThreads #-}
  getNumThreads :: Handler (ReaderT r m) prog -> ReaderT r m Word64
getNumThreads = m Word64 -> ReaderT r m Word64
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Word64 -> ReaderT r m Word64)
-> (Handler m prog -> m Word64)
-> Handler m prog
-> ReaderT r m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m Word64
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> m Word64
getNumThreads
  {-# INLINABLE getNumThreads #-}
  getFacts :: Handler (ReaderT r m) prog -> ReaderT r m (c a)
getFacts = m (c a) -> ReaderT r m (c a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (c a) -> ReaderT r m (c a))
-> (Handler m prog -> m (c a))
-> Handler m prog
-> ReaderT r m (c a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m (c a)
forall (m :: * -> *) a prog (c :: * -> *).
(MonadSouffle m, Fact a, ContainsOutputFact prog a,
 CollectFacts m c) =>
Handler m prog -> m (c a)
getFacts
  {-# INLINABLE getFacts #-}
  findFact :: Handler (ReaderT r m) prog -> a -> ReaderT r m (Maybe a)
findFact Handler (ReaderT r m) prog
prog = m (Maybe a) -> ReaderT r m (Maybe a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a) -> ReaderT r m (Maybe a))
-> (a -> m (Maybe a)) -> a -> ReaderT r m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m (Maybe a)
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsOutputFact prog a, Eq a,
 SubmitFacts m a) =>
Handler m prog -> a -> m (Maybe a)
findFact Handler m prog
Handler (ReaderT r m) prog
prog
  {-# INLINABLE findFact #-}
  addFact :: Handler (ReaderT r m) prog -> a -> ReaderT r m ()
addFact Handler (ReaderT r m) prog
fact = m () -> ReaderT r m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT r m ()) -> (a -> m ()) -> a -> ReaderT r m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m ()
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> a -> m ()
addFact Handler m prog
Handler (ReaderT r m) prog
fact
  {-# INLINABLE addFact #-}
  addFacts :: Handler (ReaderT r m) prog -> t a -> ReaderT r m ()
addFacts Handler (ReaderT r m) prog
facts = m () -> ReaderT r m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT r m ()) -> (t a -> m ()) -> t a -> ReaderT r m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> t a -> m ()
forall (m :: * -> *) (t :: * -> *) a prog.
(MonadSouffle m, Foldable t, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> t a -> m ()
addFacts Handler m prog
Handler (ReaderT r m) prog
facts
  {-# INLINABLE addFacts #-}

instance (Monoid w, MonadSouffle m) => MonadSouffle (WriterT w m) where
  type Handler (WriterT w m) = Handler m
  type CollectFacts (WriterT w m) c = CollectFacts m c
  type SubmitFacts (WriterT w m) a = SubmitFacts m a

  run :: Handler (WriterT w m) prog -> WriterT w m ()
run = m () -> WriterT w m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ())
-> (Handler m prog -> m ()) -> Handler m prog -> WriterT w m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m ()
forall (m :: * -> *) prog. MonadSouffle m => Handler m prog -> m ()
run
  {-# INLINABLE run #-}
  setNumThreads :: Handler (WriterT w m) prog -> Word64 -> WriterT w m ()
setNumThreads Handler (WriterT w m) prog
prog = m () -> WriterT w m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ())
-> (Word64 -> m ()) -> Word64 -> WriterT w m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> Word64 -> m ()
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> Word64 -> m ()
setNumThreads Handler m prog
Handler (WriterT w m) prog
prog
  {-# INLINABLE setNumThreads #-}
  getNumThreads :: Handler (WriterT w m) prog -> WriterT w m Word64
getNumThreads = m Word64 -> WriterT w m Word64
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Word64 -> WriterT w m Word64)
-> (Handler m prog -> m Word64)
-> Handler m prog
-> WriterT w m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m Word64
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> m Word64
getNumThreads
  {-# INLINABLE getNumThreads #-}
  getFacts :: Handler (WriterT w m) prog -> WriterT w m (c a)
getFacts = m (c a) -> WriterT w m (c a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (c a) -> WriterT w m (c a))
-> (Handler m prog -> m (c a))
-> Handler m prog
-> WriterT w m (c a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m (c a)
forall (m :: * -> *) a prog (c :: * -> *).
(MonadSouffle m, Fact a, ContainsOutputFact prog a,
 CollectFacts m c) =>
Handler m prog -> m (c a)
getFacts
  {-# INLINABLE getFacts #-}
  findFact :: Handler (WriterT w m) prog -> a -> WriterT w m (Maybe a)
findFact Handler (WriterT w m) prog
prog = m (Maybe a) -> WriterT w m (Maybe a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a) -> WriterT w m (Maybe a))
-> (a -> m (Maybe a)) -> a -> WriterT w m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m (Maybe a)
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsOutputFact prog a, Eq a,
 SubmitFacts m a) =>
Handler m prog -> a -> m (Maybe a)
findFact Handler m prog
Handler (WriterT w m) prog
prog
  {-# INLINABLE findFact #-}
  addFact :: Handler (WriterT w m) prog -> a -> WriterT w m ()
addFact Handler (WriterT w m) prog
fact = m () -> WriterT w m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ()) -> (a -> m ()) -> a -> WriterT w m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m ()
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> a -> m ()
addFact Handler m prog
Handler (WriterT w m) prog
fact
  {-# INLINABLE addFact #-}
  addFacts :: Handler (WriterT w m) prog -> t a -> WriterT w m ()
addFacts Handler (WriterT w m) prog
facts = m () -> WriterT w m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ()) -> (t a -> m ()) -> t a -> WriterT w m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> t a -> m ()
forall (m :: * -> *) (t :: * -> *) a prog.
(MonadSouffle m, Foldable t, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> t a -> m ()
addFacts Handler m prog
Handler (WriterT w m) prog
facts
  {-# INLINABLE addFacts #-}

instance MonadSouffle m => MonadSouffle (LazyState.StateT s m) where
  type Handler (LazyState.StateT s m) = Handler m
  type CollectFacts (LazyState.StateT s m) c = CollectFacts m c
  type SubmitFacts (LazyState.StateT s m) a = SubmitFacts m a

  run :: Handler (StateT s m) prog -> StateT s m ()
run = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (Handler m prog -> m ()) -> Handler m prog -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m ()
forall (m :: * -> *) prog. MonadSouffle m => Handler m prog -> m ()
run
  {-# INLINABLE run #-}
  setNumThreads :: Handler (StateT s m) prog -> Word64 -> StateT s m ()
setNumThreads Handler (StateT s m) prog
prog = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (Word64 -> m ()) -> Word64 -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> Word64 -> m ()
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> Word64 -> m ()
setNumThreads Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE setNumThreads #-}
  getNumThreads :: Handler (StateT s m) prog -> StateT s m Word64
getNumThreads = m Word64 -> StateT s m Word64
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Word64 -> StateT s m Word64)
-> (Handler m prog -> m Word64)
-> Handler m prog
-> StateT s m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m Word64
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> m Word64
getNumThreads
  {-# INLINABLE getNumThreads #-}
  getFacts :: Handler (StateT s m) prog -> StateT s m (c a)
getFacts = m (c a) -> StateT s m (c a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (c a) -> StateT s m (c a))
-> (Handler m prog -> m (c a))
-> Handler m prog
-> StateT s m (c a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m (c a)
forall (m :: * -> *) a prog (c :: * -> *).
(MonadSouffle m, Fact a, ContainsOutputFact prog a,
 CollectFacts m c) =>
Handler m prog -> m (c a)
getFacts
  {-# INLINABLE getFacts #-}
  findFact :: Handler (StateT s m) prog -> a -> StateT s m (Maybe a)
findFact Handler (StateT s m) prog
prog = m (Maybe a) -> StateT s m (Maybe a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a) -> StateT s m (Maybe a))
-> (a -> m (Maybe a)) -> a -> StateT s m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m (Maybe a)
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsOutputFact prog a, Eq a,
 SubmitFacts m a) =>
Handler m prog -> a -> m (Maybe a)
findFact Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE findFact #-}
  addFact :: Handler (StateT s m) prog -> a -> StateT s m ()
addFact Handler (StateT s m) prog
fact = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ()) -> (a -> m ()) -> a -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m ()
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> a -> m ()
addFact Handler m prog
Handler (StateT s m) prog
fact
  {-# INLINABLE addFact #-}
  addFacts :: Handler (StateT s m) prog -> t a -> StateT s m ()
addFacts Handler (StateT s m) prog
facts = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ()) -> (t a -> m ()) -> t a -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> t a -> m ()
forall (m :: * -> *) (t :: * -> *) a prog.
(MonadSouffle m, Foldable t, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> t a -> m ()
addFacts Handler m prog
Handler (StateT s m) prog
facts
  {-# INLINABLE addFacts #-}

instance MonadSouffle m => MonadSouffle (StrictState.StateT s m) where
  type Handler (StrictState.StateT s m) = Handler m
  type CollectFacts (StrictState.StateT s m) c = CollectFacts m c
  type SubmitFacts (StrictState.StateT s m) a = SubmitFacts m a

  run :: Handler (StateT s m) prog -> StateT s m ()
run = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (Handler m prog -> m ()) -> Handler m prog -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m ()
forall (m :: * -> *) prog. MonadSouffle m => Handler m prog -> m ()
run
  {-# INLINABLE run #-}
  setNumThreads :: Handler (StateT s m) prog -> Word64 -> StateT s m ()
setNumThreads Handler (StateT s m) prog
prog = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (Word64 -> m ()) -> Word64 -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> Word64 -> m ()
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> Word64 -> m ()
setNumThreads Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE setNumThreads #-}
  getNumThreads :: Handler (StateT s m) prog -> StateT s m Word64
getNumThreads = m Word64 -> StateT s m Word64
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Word64 -> StateT s m Word64)
-> (Handler m prog -> m Word64)
-> Handler m prog
-> StateT s m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m Word64
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> m Word64
getNumThreads
  {-# INLINABLE getNumThreads #-}
  getFacts :: Handler (StateT s m) prog -> StateT s m (c a)
getFacts = m (c a) -> StateT s m (c a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (c a) -> StateT s m (c a))
-> (Handler m prog -> m (c a))
-> Handler m prog
-> StateT s m (c a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m (c a)
forall (m :: * -> *) a prog (c :: * -> *).
(MonadSouffle m, Fact a, ContainsOutputFact prog a,
 CollectFacts m c) =>
Handler m prog -> m (c a)
getFacts
  {-# INLINABLE getFacts #-}
  findFact :: Handler (StateT s m) prog -> a -> StateT s m (Maybe a)
findFact Handler (StateT s m) prog
prog = m (Maybe a) -> StateT s m (Maybe a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a) -> StateT s m (Maybe a))
-> (a -> m (Maybe a)) -> a -> StateT s m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m (Maybe a)
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsOutputFact prog a, Eq a,
 SubmitFacts m a) =>
Handler m prog -> a -> m (Maybe a)
findFact Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE findFact #-}
  addFact :: Handler (StateT s m) prog -> a -> StateT s m ()
addFact Handler (StateT s m) prog
fact = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ()) -> (a -> m ()) -> a -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m ()
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> a -> m ()
addFact Handler m prog
Handler (StateT s m) prog
fact
  {-# INLINABLE addFact #-}
  addFacts :: Handler (StateT s m) prog -> t a -> StateT s m ()
addFacts Handler (StateT s m) prog
facts = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ()) -> (t a -> m ()) -> t a -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> t a -> m ()
forall (m :: * -> *) (t :: * -> *) a prog.
(MonadSouffle m, Foldable t, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> t a -> m ()
addFacts Handler m prog
Handler (StateT s m) prog
facts
  {-# INLINABLE addFacts #-}

instance (MonadSouffle m, Monoid w) => MonadSouffle (LazyRWS.RWST r w s m) where
  type Handler (LazyRWS.RWST r w s m) = Handler m
  type CollectFacts (LazyRWS.RWST r w s m) c = CollectFacts m c
  type SubmitFacts (LazyRWS.RWST r w s m) a = SubmitFacts m a

  run :: Handler (RWST r w s m) prog -> RWST r w s m ()
run = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (Handler m prog -> m ()) -> Handler m prog -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m ()
forall (m :: * -> *) prog. MonadSouffle m => Handler m prog -> m ()
run
  {-# INLINABLE run #-}
  setNumThreads :: Handler (RWST r w s m) prog -> Word64 -> RWST r w s m ()
setNumThreads Handler (RWST r w s m) prog
prog = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (Word64 -> m ()) -> Word64 -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> Word64 -> m ()
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> Word64 -> m ()
setNumThreads Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE setNumThreads #-}
  getNumThreads :: Handler (RWST r w s m) prog -> RWST r w s m Word64
getNumThreads = m Word64 -> RWST r w s m Word64
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Word64 -> RWST r w s m Word64)
-> (Handler m prog -> m Word64)
-> Handler m prog
-> RWST r w s m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m Word64
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> m Word64
getNumThreads
  {-# INLINABLE getNumThreads #-}
  getFacts :: Handler (RWST r w s m) prog -> RWST r w s m (c a)
getFacts = m (c a) -> RWST r w s m (c a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (c a) -> RWST r w s m (c a))
-> (Handler m prog -> m (c a))
-> Handler m prog
-> RWST r w s m (c a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m (c a)
forall (m :: * -> *) a prog (c :: * -> *).
(MonadSouffle m, Fact a, ContainsOutputFact prog a,
 CollectFacts m c) =>
Handler m prog -> m (c a)
getFacts
  {-# INLINABLE getFacts #-}
  findFact :: Handler (RWST r w s m) prog -> a -> RWST r w s m (Maybe a)
findFact Handler (RWST r w s m) prog
prog = m (Maybe a) -> RWST r w s m (Maybe a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a) -> RWST r w s m (Maybe a))
-> (a -> m (Maybe a)) -> a -> RWST r w s m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m (Maybe a)
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsOutputFact prog a, Eq a,
 SubmitFacts m a) =>
Handler m prog -> a -> m (Maybe a)
findFact Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE findFact #-}
  addFact :: Handler (RWST r w s m) prog -> a -> RWST r w s m ()
addFact Handler (RWST r w s m) prog
fact = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ()) -> (a -> m ()) -> a -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m ()
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> a -> m ()
addFact Handler m prog
Handler (RWST r w s m) prog
fact
  {-# INLINABLE addFact #-}
  addFacts :: Handler (RWST r w s m) prog -> t a -> RWST r w s m ()
addFacts Handler (RWST r w s m) prog
facts = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (t a -> m ()) -> t a -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> t a -> m ()
forall (m :: * -> *) (t :: * -> *) a prog.
(MonadSouffle m, Foldable t, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> t a -> m ()
addFacts Handler m prog
Handler (RWST r w s m) prog
facts
  {-# INLINABLE addFacts #-}

instance (MonadSouffle m, Monoid w) => MonadSouffle (StrictRWS.RWST r w s m) where
  type Handler (StrictRWS.RWST r w s m) = Handler m
  type CollectFacts (StrictRWS.RWST r w s m) c = CollectFacts m c
  type SubmitFacts (StrictRWS.RWST r w s m) a = SubmitFacts m a

  run :: Handler (RWST r w s m) prog -> RWST r w s m ()
run = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (Handler m prog -> m ()) -> Handler m prog -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m ()
forall (m :: * -> *) prog. MonadSouffle m => Handler m prog -> m ()
run
  {-# INLINABLE run #-}
  setNumThreads :: Handler (RWST r w s m) prog -> Word64 -> RWST r w s m ()
setNumThreads Handler (RWST r w s m) prog
prog = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (Word64 -> m ()) -> Word64 -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> Word64 -> m ()
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> Word64 -> m ()
setNumThreads Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE setNumThreads #-}
  getNumThreads :: Handler (RWST r w s m) prog -> RWST r w s m Word64
getNumThreads = m Word64 -> RWST r w s m Word64
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Word64 -> RWST r w s m Word64)
-> (Handler m prog -> m Word64)
-> Handler m prog
-> RWST r w s m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m Word64
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> m Word64
getNumThreads
  {-# INLINABLE getNumThreads #-}
  getFacts :: Handler (RWST r w s m) prog -> RWST r w s m (c a)
getFacts = m (c a) -> RWST r w s m (c a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (c a) -> RWST r w s m (c a))
-> (Handler m prog -> m (c a))
-> Handler m prog
-> RWST r w s m (c a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m (c a)
forall (m :: * -> *) a prog (c :: * -> *).
(MonadSouffle m, Fact a, ContainsOutputFact prog a,
 CollectFacts m c) =>
Handler m prog -> m (c a)
getFacts
  {-# INLINABLE getFacts #-}
  findFact :: Handler (RWST r w s m) prog -> a -> RWST r w s m (Maybe a)
findFact Handler (RWST r w s m) prog
prog = m (Maybe a) -> RWST r w s m (Maybe a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a) -> RWST r w s m (Maybe a))
-> (a -> m (Maybe a)) -> a -> RWST r w s m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m (Maybe a)
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsOutputFact prog a, Eq a,
 SubmitFacts m a) =>
Handler m prog -> a -> m (Maybe a)
findFact Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE findFact #-}
  addFact :: Handler (RWST r w s m) prog -> a -> RWST r w s m ()
addFact Handler (RWST r w s m) prog
fact = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ()) -> (a -> m ()) -> a -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m ()
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> a -> m ()
addFact Handler m prog
Handler (RWST r w s m) prog
fact
  {-# INLINABLE addFact #-}
  addFacts :: Handler (RWST r w s m) prog -> t a -> RWST r w s m ()
addFacts Handler (RWST r w s m) prog
facts = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (t a -> m ()) -> t a -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> t a -> m ()
forall (m :: * -> *) (t :: * -> *) a prog.
(MonadSouffle m, Foldable t, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> t a -> m ()
addFacts Handler m prog
Handler (RWST r w s m) prog
facts
  {-# INLINABLE addFacts #-}

instance MonadSouffle m => MonadSouffle (ExceptT e m) where
  type Handler (ExceptT e m) = Handler m
  type CollectFacts (ExceptT e m) c = CollectFacts m c
  type SubmitFacts (ExceptT e m) a = SubmitFacts m a

  run :: Handler (ExceptT e m) prog -> ExceptT e m ()
run = m () -> ExceptT e m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ExceptT e m ())
-> (Handler m prog -> m ()) -> Handler m prog -> ExceptT e m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m ()
forall (m :: * -> *) prog. MonadSouffle m => Handler m prog -> m ()
run
  {-# INLINABLE run #-}
  setNumThreads :: Handler (ExceptT e m) prog -> Word64 -> ExceptT e m ()
setNumThreads Handler (ExceptT e m) prog
prog = m () -> ExceptT e m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ExceptT e m ())
-> (Word64 -> m ()) -> Word64 -> ExceptT e m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> Word64 -> m ()
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> Word64 -> m ()
setNumThreads Handler m prog
Handler (ExceptT e m) prog
prog
  {-# INLINABLE setNumThreads #-}
  getNumThreads :: Handler (ExceptT e m) prog -> ExceptT e m Word64
getNumThreads = m Word64 -> ExceptT e m Word64
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Word64 -> ExceptT e m Word64)
-> (Handler m prog -> m Word64)
-> Handler m prog
-> ExceptT e m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m Word64
forall (m :: * -> *) prog.
MonadSouffle m =>
Handler m prog -> m Word64
getNumThreads
  {-# INLINABLE getNumThreads #-}
  getFacts :: Handler (ExceptT e m) prog -> ExceptT e m (c a)
getFacts = m (c a) -> ExceptT e m (c a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (c a) -> ExceptT e m (c a))
-> (Handler m prog -> m (c a))
-> Handler m prog
-> ExceptT e m (c a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> m (c a)
forall (m :: * -> *) a prog (c :: * -> *).
(MonadSouffle m, Fact a, ContainsOutputFact prog a,
 CollectFacts m c) =>
Handler m prog -> m (c a)
getFacts
  {-# INLINABLE getFacts #-}
  findFact :: Handler (ExceptT e m) prog -> a -> ExceptT e m (Maybe a)
findFact Handler (ExceptT e m) prog
prog = m (Maybe a) -> ExceptT e m (Maybe a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a) -> ExceptT e m (Maybe a))
-> (a -> m (Maybe a)) -> a -> ExceptT e m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m (Maybe a)
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsOutputFact prog a, Eq a,
 SubmitFacts m a) =>
Handler m prog -> a -> m (Maybe a)
findFact Handler m prog
Handler (ExceptT e m) prog
prog
  {-# INLINABLE findFact #-}
  addFact :: Handler (ExceptT e m) prog -> a -> ExceptT e m ()
addFact Handler (ExceptT e m) prog
fact = m () -> ExceptT e m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ExceptT e m ()) -> (a -> m ()) -> a -> ExceptT e m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> a -> m ()
forall (m :: * -> *) a prog.
(MonadSouffle m, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> a -> m ()
addFact Handler m prog
Handler (ExceptT e m) prog
fact
  {-# INLINABLE addFact #-}
  addFacts :: Handler (ExceptT e m) prog -> t a -> ExceptT e m ()
addFacts Handler (ExceptT e m) prog
facts = m () -> ExceptT e m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ExceptT e m ()) -> (t a -> m ()) -> t a -> ExceptT e m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> t a -> m ()
forall (m :: * -> *) (t :: * -> *) a prog.
(MonadSouffle m, Foldable t, Fact a, ContainsInputFact prog a,
 SubmitFacts m a) =>
Handler m prog -> t a -> m ()
addFacts Handler m prog
Handler (ExceptT e m) prog
facts
  {-# INLINABLE addFacts #-}

-- | A mtl-style typeclass for Souffle-related actions that involve file IO.
type MonadSouffleFileIO :: (Type -> Type) -> Constraint
class MonadSouffle m => MonadSouffleFileIO m where
  -- | Load all facts from files in a certain directory.
  loadFiles :: Handler m prog -> FilePath -> m ()

  -- | Write out all facts of the program to CSV files in a certain directory
  --   (as defined in the Souffle program).
  writeFiles :: Handler m prog -> FilePath -> m ()

instance MonadSouffleFileIO m => MonadSouffleFileIO (ReaderT r m) where
  loadFiles :: Handler (ReaderT r m) prog -> String -> ReaderT r m ()
loadFiles Handler (ReaderT r m) prog
prog = m () -> ReaderT r m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT r m ())
-> (String -> m ()) -> String -> ReaderT r m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
loadFiles Handler m prog
Handler (ReaderT r m) prog
prog
  {-# INLINABLE loadFiles #-}
  writeFiles :: Handler (ReaderT r m) prog -> String -> ReaderT r m ()
writeFiles Handler (ReaderT r m) prog
prog = m () -> ReaderT r m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT r m ())
-> (String -> m ()) -> String -> ReaderT r m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
writeFiles Handler m prog
Handler (ReaderT r m) prog
prog
  {-# INLINABLE writeFiles #-}

instance (Monoid w, MonadSouffleFileIO m) => MonadSouffleFileIO (WriterT w m) where
  loadFiles :: Handler (WriterT w m) prog -> String -> WriterT w m ()
loadFiles Handler (WriterT w m) prog
prog = m () -> WriterT w m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ())
-> (String -> m ()) -> String -> WriterT w m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
loadFiles Handler m prog
Handler (WriterT w m) prog
prog
  {-# INLINABLE loadFiles #-}
  writeFiles :: Handler (WriterT w m) prog -> String -> WriterT w m ()
writeFiles Handler (WriterT w m) prog
prog = m () -> WriterT w m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ())
-> (String -> m ()) -> String -> WriterT w m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
writeFiles Handler m prog
Handler (WriterT w m) prog
prog
  {-# INLINABLE writeFiles #-}

instance MonadSouffleFileIO m => MonadSouffleFileIO (StrictState.StateT s m) where
  loadFiles :: Handler (StateT s m) prog -> String -> StateT s m ()
loadFiles Handler (StateT s m) prog
prog = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (String -> m ()) -> String -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
loadFiles Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE loadFiles #-}
  writeFiles :: Handler (StateT s m) prog -> String -> StateT s m ()
writeFiles Handler (StateT s m) prog
prog = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (String -> m ()) -> String -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
writeFiles Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE writeFiles #-}

instance MonadSouffleFileIO m => MonadSouffleFileIO (LazyState.StateT s m) where
  loadFiles :: Handler (StateT s m) prog -> String -> StateT s m ()
loadFiles Handler (StateT s m) prog
prog = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (String -> m ()) -> String -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
loadFiles Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE loadFiles #-}
  writeFiles :: Handler (StateT s m) prog -> String -> StateT s m ()
writeFiles Handler (StateT s m) prog
prog = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ())
-> (String -> m ()) -> String -> StateT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
writeFiles Handler m prog
Handler (StateT s m) prog
prog
  {-# INLINABLE writeFiles #-}

instance (MonadSouffleFileIO m, Monoid w) => MonadSouffleFileIO (LazyRWS.RWST r w s m) where
  loadFiles :: Handler (RWST r w s m) prog -> String -> RWST r w s m ()
loadFiles Handler (RWST r w s m) prog
prog = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (String -> m ()) -> String -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
loadFiles Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE loadFiles #-}
  writeFiles :: Handler (RWST r w s m) prog -> String -> RWST r w s m ()
writeFiles Handler (RWST r w s m) prog
prog = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (String -> m ()) -> String -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
writeFiles Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE writeFiles #-}

instance (MonadSouffleFileIO m, Monoid w) => MonadSouffleFileIO (StrictRWS.RWST r w s m) where
  loadFiles :: Handler (RWST r w s m) prog -> String -> RWST r w s m ()
loadFiles Handler (RWST r w s m) prog
prog = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (String -> m ()) -> String -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
loadFiles Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE loadFiles #-}
  writeFiles :: Handler (RWST r w s m) prog -> String -> RWST r w s m ()
writeFiles Handler (RWST r w s m) prog
prog = m () -> RWST r w s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ())
-> (String -> m ()) -> String -> RWST r w s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
writeFiles Handler m prog
Handler (RWST r w s m) prog
prog
  {-# INLINABLE writeFiles #-}

instance MonadSouffleFileIO m => MonadSouffleFileIO (ExceptT s m) where
  loadFiles :: Handler (ExceptT s m) prog -> String -> ExceptT s m ()
loadFiles Handler (ExceptT s m) prog
prog = m () -> ExceptT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ExceptT s m ())
-> (String -> m ()) -> String -> ExceptT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
loadFiles Handler m prog
Handler (ExceptT s m) prog
prog
  {-# INLINABLE loadFiles #-}
  writeFiles :: Handler (ExceptT s m) prog -> String -> ExceptT s m ()
writeFiles Handler (ExceptT s m) prog
prog = m () -> ExceptT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ExceptT s m ())
-> (String -> m ()) -> String -> ExceptT s m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m prog -> String -> m ()
forall (m :: * -> *) prog.
MonadSouffleFileIO m =>
Handler m prog -> String -> m ()
writeFiles Handler m prog
Handler (ExceptT s m) prog
prog
  {-# INLINABLE writeFiles #-}