-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A simple memoization helper library
--   
--   This library encourages you to do memoization in three separate steps:
--   
--   <ol>
--   <li>Create a memoizable function</li>
--   <li>Create or select an appropriate memoizer</li>
--   <li>Run the memoizer on the memoizable function</li>
--   </ol>
--   
--   Let's start with the first. When you create a memoizable function, you
--   should use the <tt>self</tt> convention, which is that the first input
--   to the function is <tt>self</tt>, and all recursive calls are replaced
--   with <tt>self</tt>. One common convention that goes well with the
--   <tt>self</tt> convention is using a helper function <tt>go</tt>, like
--   so:
--   
--   <pre>
--   fib :: Memoizable (Integer -&gt; Integer)
--   fib self = go
--     where go 0 = 1
--           go 1 = 1
--           go n = self (n-1) + self (n-2)
--   </pre>
--   
--   Now for the second. For this example, we need a Memoizer that can
--   handle an <tt>Integer</tt> input, and an <tt>Integer</tt> output.
--   <tt>Data.MemoCombinators</tt> provides <tt>integral</tt>, which
--   handles any <tt>Integral</tt> input, and any output.
--   <tt>Data.MemoUgly</tt> provides <tt>memo</tt>, which can memoize any
--   function <tt>a -&gt; b</tt>, given an <tt>Ord</tt> instance for
--   <tt>a</tt>.
--   
--   Third, let's run our memoizers! Since we have decoupled the definition
--   of the memoized function from its actual memoization, we can create
--   multiple memoized versions of the same function if we so desire.
--   
--   <pre>
--   import qualified Data.MemoUgly as Ugly
--   import qualified Data.MemoCombinators as MC
--   
--   fibUgly :: Integer -&gt; Integer
--   fibUgly = runMemo Ugly.memo fib
--   
--   fibMC :: Integer -&gt; Integer
--   fibMC = runMemo MC.integral fib
--   </pre>
--   
--   You could easily do the same with <tt>Data.MemoTrie.memo</tt>,
--   <tt>Data.Function.Memoize.memoize</tt>, etc.
--   
--   Using this technique, you can create local memoized functions whose
--   memo tables are garbage collected as soon as they are no longer
--   needed.
@package runmemo
@version 1.0.0.1


-- | Run <a>Memoizer</a>s on <a>Memoizable</a> functions. The beauty of
--   <a>runMemo</a> is that it decouples the definition of a Memoizable
--   function from the process of actually memoizing it.
module Data.RunMemo

-- | A memoizable thing takes itself as input and produces itself.
--   
--   Usually you will use this for functions: e.g. <tt>foo :: Memoizable
--   (String -&gt; String)</tt>, which desugars to <tt>foo :: (String -&gt;
--   String) -&gt; String -&gt; String</tt>
type Memoizable a = a -> a

-- | A memoizer from a to b takes a function with input a and output b and
--   memoizes it
--   
--   If you have a <tt>Memo Foo</tt> from <tt>Data.MemoCombinators</tt>,
--   then it is also a <tt>Memoizer Foo b</tt>, which can unify with any
--   type <tt>b</tt>.
type Memoizer a b = (a -> b) -> a -> b

-- | Given a memoizable function and a memoizer, put two and two together!
--   
--   Your memoizable should look something like this:
--   
--   <pre>
--   foo :: Memoizable (Foo -&gt; Bar)
--   foo self = go
--     where go x = ... self a ...
--   </pre>
--   
--   The main feature is that <tt>self</tt> is the first input of a
--   <tt>Memoizable</tt> function, <tt>self</tt> and is used for all
--   recursive calls.
--   
--   Memoizables can take as many arguments as you like, given an
--   appropriate Memoizer
--   
--   <pre>
--   foo2 :: Memoizable (Bar -&gt; Baz -&gt; Quux)
--   foo2 self = go
--     where go x y = ... self a b ...
--   </pre>
--   
--   Using <tt>Data.MemoCombinators</tt>, for example, you could do
--   <tt>runMemo (Memo.memo2 Memo.bar Memo.baz) foo2</tt>
runMemo :: Memoizer a b -> Memoizable (a -> b) -> a -> b

-- | The trivial memoizer. It doesn't actually memoize anything, it just
--   passes values straight through to the original function.
--   
--   It is not recommended that you actually use this memoizer.
noMemo :: Memoizer a b
