You may find Data.MemoCombinators useful (in the data-memocombators package).
You do not say which argument your f
and g
, if they both take integer values, then you will use it as follows:
import qualified Data.MemoCombinators as Memo foo = iterate step (Memo.integral f0, Memo.integral g0)
If necessary, you can also save the output of each step.
step (f,g) = (Memo.integral (newF fg), Memo.integral (newG fg))
Hopefully you won't see this breaking the whole program.
In response to your comment:
This is the best I can think of. It has not been tested, but should work on the correct lines.
I'm worried that converting between Double
and Rational
uselessly inefficient --- if there was a Bits
instance for Double
, we could use Memo.bits
. Therefore, it may not ultimately be useful to you.
import Control.Arrow ((&&&)) import Data.Ratio (numerator, denominator, (%)) memoV :: Memo.Memo a -> Memo.Memo (V a) memoV mf = \(V xyz) -> table xyz where gxyz = f (V xyz) table = Memo.memo3 mmmg memoRealFrac :: RealFrac a => Memo.Memo a memoRealFrac f = Memo.wrap (fromRational . uncurry (%)) ((numerator &&& denominator) . toRational) Memo.integral
Another approach.
You have
step :: (V Double -> V Double, V Double -> V Double) -> (V Double -> V Double, V Double -> V Double)
How about you change this to
step :: (V Double -> (V Double, V Double)) -> (V Double -> (V Double, V Double)) step hx = (r fx gx, s fx gx) where (fx, gx) = hx
And also change
foo = (fst . bar, snd . bar) where bar = iterate step (f0 &&& g0)
We hope that the common fx
and gx
should lead to acceleration.