Safe Haskell | Safe-Inferred |
---|
Run Memoizer
s on Memoizable
functions.
The beauty of runMemo
is that it decouples
the definition of a Memoizable function
from the process of actually memoizing it.
- type Memoizable a = a -> a
- type Memoizer a b = (a -> b) -> a -> b
- runMemo :: Memoizer a b -> Memoizable (a -> b) -> a -> b
- noMemo :: Memoizer a b
Documentation
type Memoizable a = a -> aSource
A memoizable thing takes itself as input and produces itself.
Usually you will use this for functions:
e.g. foo :: Memoizable (String -> String)
,
which desugars to foo :: (String -> String) -> String -> String
type Memoizer a b = (a -> b) -> a -> bSource
A memoizer from a to b takes a function with input a and output b and memoizes it
If you have a Memo Foo
from Data.MemoCombinators
,
then it is also a Memoizer Foo b
, which can unify
with any type b
.
runMemo :: Memoizer a b -> Memoizable (a -> b) -> a -> bSource
Given a memoizable function and a memoizer, put two and two together!
Your memoizable should look something like this:
foo :: Memoizable (Foo -> Bar) foo self = go where go x = ... self a ...
The main feature is that self
is the first input
of a Memoizable
function,
self
and is used for all recursive calls.
Memoizables can take as many arguments as you like, given an appropriate Memoizer
foo2 :: Memoizable (Bar -> Baz -> Quux) foo2 self = go where go x y = ... self a b ...
Using Data.MemoCombinators
, for example,
you could do runMemo (Memo.memo2 Memo.bar Memo.baz) foo2