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

Safe Haskell None Haskell2010

Haxl.Core.Monad

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 w 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 writer monad for WriteTree. We strongly advise these be used only for logs used for debugging. These are not memoized. Other relevant writes should be returned as function output, which is the more "functional" way.

Constructors

 GenHaxl FieldsunHaxl :: Env u w -> IO (Result u w a)
Instances
 Monad (GenHaxl u w) Source # Instance detailsDefined in Haxl.Core.Monad Methods(>>=) :: GenHaxl u w a -> (a -> GenHaxl u w b) -> GenHaxl u w b #(>>) :: GenHaxl u w a -> GenHaxl u w b -> GenHaxl u w b #return :: a -> GenHaxl u w a #fail :: String -> GenHaxl u w a # Functor (GenHaxl u w) Source # Instance detailsDefined in Haxl.Core.Monad Methodsfmap :: (a -> b) -> GenHaxl u w a -> GenHaxl u w b #(<$) :: a -> GenHaxl u w b -> GenHaxl u w a # Applicative (GenHaxl u w) Source # Instance detailsDefined in Haxl.Core.Monad Methodspure :: a -> GenHaxl u w a #(<*>) :: GenHaxl u w (a -> b) -> GenHaxl u w a -> GenHaxl u w b #liftA2 :: (a -> b -> c) -> GenHaxl u w a -> GenHaxl u w b -> GenHaxl u w c #(*>) :: GenHaxl u w a -> GenHaxl u w b -> GenHaxl u w b #(<*) :: GenHaxl u w a -> GenHaxl u w b -> GenHaxl u w a # MonadThrow (GenHaxl u w) Source # Since: 0.3.1.0 Instance detailsDefined in Haxl.Core.Monad MethodsthrowM :: Exception e => e -> GenHaxl u w a # MonadCatch (GenHaxl u w) Source # Since: 0.3.1.0 Instance detailsDefined in Haxl.Core.Monad Methodscatch :: Exception e => GenHaxl u w a -> (e -> GenHaxl u w a) -> GenHaxl u w a # Fractional a => Fractional (GenHaxl u w a) Source # Instance detailsDefined in Haxl.Prelude Methods(/) :: GenHaxl u w a -> GenHaxl u w a -> GenHaxl u w a #recip :: GenHaxl u w a -> GenHaxl u w a #fromRational :: Rational -> GenHaxl u w a # Num a => Num (GenHaxl u w a) Source # Instance detailsDefined in Haxl.Prelude Methods(+) :: GenHaxl u w a -> GenHaxl u w a -> GenHaxl u w a #(-) :: GenHaxl u w a -> GenHaxl u w a -> GenHaxl u w a #(*) :: GenHaxl u w a -> GenHaxl u w a -> GenHaxl u w a #negate :: GenHaxl u w a -> GenHaxl u w a #abs :: GenHaxl u w a -> GenHaxl u w a #signum :: GenHaxl u w a -> GenHaxl u w a #fromInteger :: Integer -> GenHaxl u w a # IsString a => IsString (GenHaxl u w a) Source # Instance detailsDefined in Haxl.Core.Monad MethodsfromString :: String -> GenHaxl u w a # u1 ~ u2 => IfThenElse (GenHaxl u1 w Bool) (GenHaxl u2 w a) Source # Instance detailsDefined in Haxl.Prelude MethodsifThenElse :: GenHaxl u1 w Bool -> GenHaxl u2 w a -> GenHaxl u2 w a -> GenHaxl u2 w a Source # data Result u w 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 w b) (Cont u w 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 w a, but see IVar, Instances  Show a => Show (Result u w a) Source # Instance detailsDefined in Haxl.Core.Monad MethodsshowsPrec :: Int -> Result u w a -> ShowS #show :: Result u w a -> String #showList :: [Result u w a] -> ShowS # # Writes (for debugging only) data WriteTree w Source # A tree of writes done during a Haxl computation. We could use a simple list, but this allows us to avoid multiple mappends when concatenating writes from two haxl computations. Users should try to treat this data type as opaque, and prefer to use flattenWT to get a simple list of writes from a WriteTree. Constructors  NilWrites SomeWrite w MergeWrites (WriteTree w) (WriteTree w) Instances  Show w => Show (WriteTree w) Source # Instance detailsDefined in Haxl.Core.Monad MethodsshowsPrec :: Int -> WriteTree w -> ShowS #show :: WriteTree w -> String #showList :: [WriteTree w] -> ShowS # tellWrite :: w -> GenHaxl u w () Source # write :: WriteTree w -> GenHaxl u w () Source # # Cont data Cont u w 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 w a) (Cont u w b) :>>= (b -> GenHaxl u w a) (b -> a) :<$> (Cont u w b)

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

# IVar

newtype IVar u w a Source #

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

Constructors

 IVar (IORef (IVarContents u w a))

data IVarContents u w a Source #

Constructors

 IVarFull (ResultVal a w) IVarEmpty (JobList u w)

newIVar :: IO (IVar u w a) Source #

newFullIVar :: ResultVal a w -> IO (IVar u w a) Source #

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

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

# ResultVal

data ResultVal a w 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.

Constructors

 Ok a (WriteTree w) ThrowHaxl SomeException (WriteTree w) ThrowIO SomeException

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

# CompleteReq

data CompleteReq u w 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 w a) !Int64

# Env

data Env u w Source #

The data we carry around in the Haxl monad.

Constructors

 Env FieldscacheRef :: !(IORef (DataCache (IVar u w)))cached data fetchesmemoRef :: !(IORef (DataCache (IVar u w)))memoized computationsflags :: !Flags userEnv :: uuser-supplied data, retrievable with envstatsRef :: !(IORef Stats)statistics, collected according to the report level in flags.profLabel :: ProfileLabelcurrent profiling label, see withLabelprofRef :: !(IORef Profile)profiling data, collected according to the report level in flags.states :: StateStoreData sources and other components can store their state in here. Items in this store must be instances of StateKey.reqStoreRef :: !(IORef (RequestStore u))The set of requests that we have not submitted to data sources yet. Owned by the scheduler.runQueueRef :: !(IORef (JobList u w))runnable computations. Things get added to here when we wake up a computation that was waiting for something. When the list is empty, either we're finished, or we're waiting for some data fetch to return.submittedReqsRef :: !(IORef ReqCountMap)all outgone fetches which haven't yet returned. Entries are removed from this map as the fetches finish. This field is useful for tracking outgone fetches to detect downstream failures.completions :: !(TVar [CompleteReq u w])Requests that have completed. Modified by data sources (via putResult) and the scheduler. Waiting for this list to become non-empty is how the scheduler blocks waiting for data fetches to return.pendingWaits :: [IO ()]this is a list of IO actions returned by FutureFetch data sources. These do a blocking wait for the results of some data fetch.speculative :: !Int writeLogsRef :: !(IORef (WriteTree w))A log of all writes done as part of this haxl computation. Any haxl computation that needs to be memoized runs in its own environment so

type Caches u w = (IORef (DataCache (IVar u w)), IORef (DataCache (IVar u w))) Source #

caches :: Env u w -> Caches u w Source #

initEnvWithData :: StateStore -> u -> Caches u w -> IO (Env u w) 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 w) Source #

Initializes an environment with StateStore and an input map.

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

A new, empty environment.

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

Extracts data from the Env.

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

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

speculate :: Env u w -> Env u w Source #

imperative :: Env u w -> Env u w Source #

# JobList

data JobList u w 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 w) (GenHaxl u w a) !(IVar u w a) (JobList u w)

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

# Exceptions

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

Throw an exception in the Haxl monad

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

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

Catch an exception in the Haxl monad

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

Catch exceptions that satisfy a predicate

try :: Exception e => GenHaxl u w a -> GenHaxl u w (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 w a -> GenHaxl u w (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

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 w ()
loadCache = do
cacheRequest (ListWombats 3) (Right ([1,2,3]))
cacheRequest (CountAardvarks "abcabc") (Right (2))

Dump the contents of the cache as Haskell code that, when compiled and run, will recreate the same cache contents. Does not take into account the writes done as part of the computation.

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

# Unsafe operations

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

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

unsafeToHaxlException :: GenHaxl u w a -> GenHaxl u w 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.