cached-0.1.0.0: Cache values to disk.

Safe HaskellNone
LanguageHaskell2010

Data.Cached

Contents

Description

Usage

A value of type "Cached a" should be understood as a value of type "a" that is read from a file, or that is produced from data stored in one or more files, or from arbitrary IO actions.

Cached values can be created from pure values,

>>> let a = cache' "/tmp/cached-ex/a" (pure 1) :: Cached Int

or from files stored on disk.

>>> let b = source' "/tmp/cached-ex/b" :: Cached Int

Use the functor and applicative instances to use cached values in new computations.

>>> let bigA = fmap (* 2) a
>>> let c = (+) <$> a <*> b

The cached value "c" represents a value produced by summing together the values stored in "/tmp/cached-ex/a" and "/tmp/cached-ex/b". It is not yet associated to its own cache file. To actually store it into a cache file, use cache' (or cache for values that are not instances of Show and Read or when you want to control the file format, e.g. writing arrays to CSV files)

>>> let c' = cache' "/tmp/cached-ex/c" c

Running the cached computation "c'" will execute all necessary computations and write results to files as expected:

>>> -- Before running, let's make sure the target directory is clean.
>>> :!mkdir -p /tmp/cached-ex
>>> :!rm -f /tmp/cached-ex/*
>>> :!echo 2 > /tmp/cached-ex/b
>>> 
>>> runShake "/tmp/cached-ex/.shake" c'
# Writing cache (for /tmp/cached-ex/a)
# Writing cache (for /tmp/cached-ex/c)
Build completed ...
...

Running it again won't run anything. Since none of the cached or source files have changed, there is nothing to re-compute.

>>> runShake "/tmp/cached-ex/.shake" c'
Build completed ...
...

If we modify the content of "/tmp/cached-ex/b", running "c'" again will only re-run the computation for "c'", and not for "a" since it does not depend on "b".

>>> :! echo 3 > /tmp/cached-ex/b
>>> runShake "/tmp/cached-ex/.shake" c'
# Writing cache (for /tmp/cached-ex/c)
Build completed ...
...

The cache files and dependencies can be inspected with prettyCached.

>>> prettyCached c' >>= putStr
Cached Value = 4
Cached Needs:
  /tmp/cached-ex/c
Cached Build:
  /tmp/cached-ex/a
  /tmp/cached-ex/c
    /tmp/cached-ex/a
    /tmp/cached-ex/b

The previous output means that the value carried by "c'" is 4, and that in order to be computed, it needs the file "/tmp/cached-ex/c". The last field, "Cached Build", lists each file that is to be built by the cache system and their dependencies: "/tmp/cache-ex/a" and "/tmp/cache-ex/c" are created by the cache system, and the latter depends on "/tmp/cache-ex/a" and "/tmp/cache-ex/b"

To put together different independent cached values into a single one so that they all get built together, use <>. However, "Cached a" is an instance of Semigroup only if "a" is. You can "sink" the cached values first, which will turn a "Cache a" into a "Cache ()", satisfying the Semigroup constraint.

>>> let d = sink' "/tmp/cached-ex/d" (pure 'd')
>>> let e = sink' "/tmp/cached-ex/e" (pure 'e')
>>> let de = d <> e
>>> prettyCached de >>= putStr
Cached Value = ()
Cached Needs:
Cached Build:
  /tmp/cached-ex/d
  /tmp/cached-ex/e
Synopsis

Cached type

data Cached a Source #

A value that is produced from files on disk or arbitrary IO actions.

Instances
Functor Cached Source # 
Instance details

Defined in Data.Cached.Internal

Methods

fmap :: (a -> b) -> Cached a -> Cached b #

(<$) :: a -> Cached b -> Cached a #

Applicative Cached Source # 
Instance details

Defined in Data.Cached.Internal

Methods

pure :: a -> Cached a #

(<*>) :: Cached (a -> b) -> Cached a -> Cached b #

liftA2 :: (a -> b -> c) -> Cached a -> Cached b -> Cached c #

(*>) :: Cached a -> Cached b -> Cached b #

(<*) :: Cached a -> Cached b -> Cached a #

Floating a => Floating (Cached a) Source # 
Instance details

Defined in Data.Cached.Internal

Methods

pi :: Cached a #

exp :: Cached a -> Cached a #

log :: Cached a -> Cached a #

sqrt :: Cached a -> Cached a #

(**) :: Cached a -> Cached a -> Cached a #

logBase :: Cached a -> Cached a -> Cached a #

sin :: Cached a -> Cached a #

cos :: Cached a -> Cached a #

tan :: Cached a -> Cached a #

asin :: Cached a -> Cached a #

acos :: Cached a -> Cached a #

atan :: Cached a -> Cached a #

sinh :: Cached a -> Cached a #

cosh :: Cached a -> Cached a #

tanh :: Cached a -> Cached a #

asinh :: Cached a -> Cached a #

acosh :: Cached a -> Cached a #

atanh :: Cached a -> Cached a #

log1p :: Cached a -> Cached a #

expm1 :: Cached a -> Cached a #

log1pexp :: Cached a -> Cached a #

log1mexp :: Cached a -> Cached a #

Fractional a => Fractional (Cached a) Source # 
Instance details

Defined in Data.Cached.Internal

Methods

(/) :: Cached a -> Cached a -> Cached a #

recip :: Cached a -> Cached a #

fromRational :: Rational -> Cached a #

Num a => Num (Cached a) Source # 
Instance details

Defined in Data.Cached.Internal

Methods

(+) :: Cached a -> Cached a -> Cached a #

(-) :: Cached a -> Cached a -> Cached a #

(*) :: Cached a -> Cached a -> Cached a #

negate :: Cached a -> Cached a #

abs :: Cached a -> Cached a #

signum :: Cached a -> Cached a #

fromInteger :: Integer -> Cached a #

Semigroup a => Semigroup (Cached a) Source # 
Instance details

Defined in Data.Cached.Internal

Methods

(<>) :: Cached a -> Cached a -> Cached a #

sconcat :: NonEmpty (Cached a) -> Cached a #

stimes :: Integral b => b -> Cached a -> Cached a #

Monoid a => Monoid (Cached a) Source # 
Instance details

Defined in Data.Cached.Internal

Methods

mempty :: Cached a #

mappend :: Cached a -> Cached a -> Cached a #

mconcat :: [Cached a] -> Cached a #

getValue :: Cached a -> IO (Either Text a) Source #

Extract the value cached value.

Creation

To create cached values from pure values, use pure.

>>> let a = pure 1 :: Cached Int
>>> prettyCached a >>= putStr
Cached Value = 1
Cached Needs:
Cached Build:

Newly created cached values won't actually be written to files or attached to IO actions yet, as denoted by the empty "Cached Build" field. To associate them with actual cache files on disk, see section "Caching values" below.

The following functions offer additionnal creation possibilities.

source :: FilePath -> (Text -> Either Text a) -> Cached a Source #

Create a cached value from an input file.

source' :: Read a => FilePath -> Cached a Source #

A convenient variant of source when the type of the value to be read instantiates Read.

fromIO :: Set FilePath -> IO a -> Cached a Source #

Create a cached value from an IO action that depends on some input files.

Caching values

These functions associate cached values to files on disk or IO actions.

cache :: FilePath -> (a -> Text) -> (Text -> Either Text a) -> Cached a -> Cached a Source #

Associate a cached value to a file on disk.

cache' :: (Show a, Read a) => FilePath -> Cached a -> Cached a Source #

A convenient variant of cache when the type of the value to be read is an instance of Read and Show.

cacheIO :: FilePath -> (a -> IO ()) -> IO (Either Text a) -> Cached a -> Cached a Source #

Caching with arbitrary IO actions.

sink :: FilePath -> (a -> Either Text Text) -> Cached a -> Cached () Source #

Associate a cached value to a file on disk without the possibility to read it back. Useful for storing to a text file the final result of a computation that doesn't need to be read again, like data for producing figures, text output, etc.

sink' :: Show a => FilePath -> Cached a -> Cached () Source #

A convenient variant of sink when the written value type instantiates Show.

sinkIO :: FilePath -> (a -> IO (Either Text ())) -> Cached a -> Cached () Source #

Sink with an arbitrary IO action.

trigger :: FilePath -> IO (Either Text ()) -> Set FilePath -> Cached () Source #

Trigger an IO action that depends on a set of files. For example, consider an executable "plot" that processes the content of a file "data.csv" and writes an image to "fig.png". The figure creation can be integrated into the cache system like so:

>>> import System.Process (callCommand)
>>> let t = trigger "fig.png" (return <$> callCommand "plot") (Set.fromList ["data.csv"])
>>> prettyCached t >>= putStr
Cached Value = ()
Cached Needs:
Cached Build:
  fig.png
    data.csv

Running

toShakeRules :: Cached a -> Rules () Source #

Get shake Rules. Those can be mixed together with other shake rules.

runShake :: FilePath -> Cached a -> IO () Source #

Run the cached computation using shake (see shakebuild.com, Development.Shake). If you use the result of this function as your program's main, you can pass shake options as arguments. Try "my-program --help"

Showing