haxl-2.0.1.0: A Haskell library for efficient, concurrent, and concise data access.

Safe HaskellNone
LanguageHaskell2010

Haxl.Core.Monad

Contents

Description

The implementation of the Haxl monad. Most users should import Haxl.Core instead of importing this module directly.

Synopsis

The monad

newtype GenHaxl u a Source #

The Haxl monad, which does several things:

  • It is a reader monad for Env, which contains the current state of the scheduler, including unfetched requests and the run queue of computations.
  • It is a concurrency, or resumption, monad. A computation may run partially and return Blocked, in which case the framework should perform the outstanding requests in the RequestStore, and then resume the computation.
  • The Applicative combinator <*> explores both branches in the event that the left branch is Blocked, so that we can collect multiple requests and submit them as a batch.
  • It contains IO, so that we can perform real data fetching.

Constructors

GenHaxl 

Fields

Instances

Monad (GenHaxl u) Source # 

Methods

(>>=) :: GenHaxl u a -> (a -> GenHaxl u b) -> GenHaxl u b #

(>>) :: GenHaxl u a -> GenHaxl u b -> GenHaxl u b #

return :: a -> GenHaxl u a #

fail :: String -> GenHaxl u a #

Functor (GenHaxl u) Source # 

Methods

fmap :: (a -> b) -> GenHaxl u a -> GenHaxl u b #

(<$) :: a -> GenHaxl u b -> GenHaxl u a #

Applicative (GenHaxl u) Source # 

Methods

pure :: a -> GenHaxl u a #

(<*>) :: GenHaxl u (a -> b) -> GenHaxl u a -> GenHaxl u b #

liftA2 :: (a -> b -> c) -> GenHaxl u a -> GenHaxl u b -> GenHaxl u c #

(*>) :: GenHaxl u a -> GenHaxl u b -> GenHaxl u b #

(<*) :: GenHaxl u a -> GenHaxl u b -> GenHaxl u a #

MonadThrow (GenHaxl u) Source #

Since: 0.3.1.0

Methods

throwM :: Exception e => e -> GenHaxl u a #

MonadCatch (GenHaxl u) Source #

Since: 0.3.1.0

Methods

catch :: Exception e => GenHaxl u a -> (e -> GenHaxl u a) -> GenHaxl u a #

IsString a => IsString (GenHaxl u a) Source # 

Methods

fromString :: String -> GenHaxl u a #

(~) * u1 u2 => IfThenElse (GenHaxl u1 Bool) (GenHaxl u2 a) Source # 

Methods

ifThenElse :: GenHaxl u1 Bool -> GenHaxl u2 a -> GenHaxl u2 a -> GenHaxl u2 a Source #

data Result u a Source #

The result of a computation is either Done with a value, Throw with an exception, or Blocked on the result of a data fetch with a continuation.

Constructors

Done a 
Throw SomeException 
Blocked !(IVar u b) (Cont u a)

The IVar is what we are blocked on; Cont is the continuation. This might be wrapped further if we're nested inside multiple >>=, before finally being added to the IVar. Morally b -> GenHaxl u a, but see IVar,

Instances

Show a => Show (Result u a) Source # 

Methods

showsPrec :: Int -> Result u a -> ShowS #

show :: Result u a -> String #

showList :: [Result u a] -> ShowS #

Cont

data Cont u a Source #

A data representation of a Haxl continuation. This is to avoid repeatedly traversing a left-biased tree in a continuation, leading O(n^2) complexity for some pathalogical cases - see the "seql" benchmark in tests/MonadBench.hs. See "A Smart View on Datatypes", Jaskelioff/Rivas, ICFP'15

Constructors

Cont (GenHaxl u a) 
(Cont u b) :>>= (b -> GenHaxl u a) 
(b -> a) :<$> (Cont u b) 

toHaxl :: Cont u a -> GenHaxl u a Source #

IVar

newtype IVar u a Source #

A synchronisation point. It either contains a value, or a list of computations waiting for the value.

Constructors

IVar (IORef (IVarContents u a)) 

data IVarContents u a Source #

Constructors

IVarFull (ResultVal a) 
IVarEmpty (JobList u) 

getIVar :: IVar u a -> GenHaxl u a Source #

putIVar :: IVar u a -> ResultVal a -> Env u -> IO () Source #

ResultVal

data ResultVal a Source #

The contents of a full IVar. We have to distinguish exceptions thrown in the IO monad from exceptions thrown in the Haxl monad, so that when the result is fetched using getIVar, we can throw the exception in the right way.

done :: ResultVal a -> IO (Result u a) Source #

CompleteReq

data CompleteReq u Source #

A completed request from a data source, containing the result, and the IVar representing the blocked computations. The job of a data source is just to add these to a queue (completions) using putResult; the scheduler collects them from the queue and unblocks the relevant computations.

Constructors

CompleteReq (Either SomeException a) !(IVar u a) !Int64 

Env

data Env u Source #

The data we carry around in the Haxl monad.

Constructors

Env 

Fields

initEnvWithData :: StateStore -> u -> Caches u -> IO (Env u) Source #

Initialize an environment with a StateStore, an input map, a preexisting DataCache, and a seed for the random number generator.

initEnv :: StateStore -> u -> IO (Env u) Source #

Initializes an environment with StateStore and an input map.

emptyEnv :: u -> IO (Env u) Source #

A new, empty environment.

env :: (Env u -> a) -> GenHaxl u a Source #

Extracts data from the Env.

withEnv :: Env u -> GenHaxl u a -> GenHaxl u a Source #

Returns a version of the Haxl computation which always uses the provided Env, ignoring the one specified by runHaxl.

JobList

data JobList u Source #

A list of computations together with the IVar into which they should put their result.

This could be an ordinary list, but the optimised representation saves space and time.

Constructors

JobNil 
JobCons (Env u) (GenHaxl u a) !(IVar u a) (JobList u) 

addJob :: Env u -> GenHaxl u b -> IVar u b -> IVar u a -> IO () Source #

Exceptions

throw :: Exception e => e -> GenHaxl u a Source #

Throw an exception in the Haxl monad

raise :: Exception e => e -> IO (Result u a) Source #

catch :: Exception e => GenHaxl u a -> (e -> GenHaxl u a) -> GenHaxl u a Source #

Catch an exception in the Haxl monad

catchIf :: Exception e => (e -> Bool) -> GenHaxl u a -> (e -> GenHaxl u a) -> GenHaxl u a Source #

Catch exceptions that satisfy a predicate

try :: Exception e => GenHaxl u a -> GenHaxl u (Either e a) Source #

Returns Left e if the computation throws an exception e, or Right a if it returns a result a.

tryToHaxlException :: GenHaxl u a -> GenHaxl u (Either HaxlException a) Source #

Like try, but lifts all exceptions into the HaxlException hierarchy. Uses unsafeToHaxlException internally. Typically this is used at the top level of a Haxl computation, to ensure that all exceptions are caught.

Dumping the cache

dumpCacheAsHaskell :: GenHaxl u String Source #

Dump the contents of the cache as Haskell code that, when compiled and run, will recreate the same cache contents. For example, the generated code looks something like this:

loadCache :: GenHaxl u ()
loadCache = do
  cacheRequest (ListWombats 3) (Right ([1,2,3]))
  cacheRequest (CountAardvarks "abcabc") (Right (2))

dumpCacheAsHaskellFn :: String -> String -> GenHaxl u String Source #

Dump the contents of the cache as Haskell code that, when compiled and run, will recreate the same cache contents.

Takes the name and type for the resulting function as arguments.

Unsafe operations

unsafeLiftIO :: IO a -> GenHaxl u a Source #

Under ordinary circumstances this is unnecessary; users of the Haxl monad should generally not perform arbitrary IO.

unsafeToHaxlException :: GenHaxl u a -> GenHaxl u a Source #

Convert exceptions in the underlying IO monad to exceptions in the Haxl monad. This is morally unsafe, because you could then catch those exceptions in Haxl and observe the underlying execution order. Not to be exposed to user code.