Safe Haskell | None |
---|---|
Language | Haskell2010 |
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
- data Cached a
- getValue :: Cached a -> IO (Either Text a)
- source :: FilePath -> (Text -> Either Text a) -> Cached a
- source' :: Read a => FilePath -> Cached a
- fromIO :: Set FilePath -> IO a -> Cached a
- cache :: FilePath -> (a -> Text) -> (Text -> Either Text a) -> Cached a -> Cached a
- cache' :: (Show a, Read a) => FilePath -> Cached a -> Cached a
- cacheIO :: FilePath -> (a -> IO ()) -> IO (Either Text a) -> Cached a -> Cached a
- sink :: FilePath -> (a -> Either Text Text) -> Cached a -> Cached ()
- sink' :: Show a => FilePath -> Cached a -> Cached ()
- sinkIO :: FilePath -> (a -> IO (Either Text ())) -> Cached a -> Cached ()
- trigger :: FilePath -> IO (Either Text ()) -> Set FilePath -> Cached ()
- toShakeRules :: Cached a -> Rules ()
- runShake :: FilePath -> Cached a -> IO ()
- prettyCached :: Show a => Cached a -> IO Text
Cached type
A value that is produced from files on disk or arbitrary IO actions.
Instances
Functor Cached Source # | |
Applicative Cached Source # | |
Floating a => Floating (Cached a) Source # | |
Defined in Data.Cached.Internal sqrt :: Cached a -> Cached a # (**) :: Cached a -> Cached a -> Cached a # logBase :: Cached a -> 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 # | |
Fractional a => Fractional (Cached a) Source # | |
Num a => Num (Cached a) Source # | |
Semigroup a => Semigroup (Cached a) Source # | |
Monoid a => Monoid (Cached a) Source # | |
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.
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.
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.
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"