Puede encontrar Data.MemoCombinators útil (en el paquete data-memocombinators).
Usted no dice qué tipos argumento de su toma y f
g
--- si ambos toma valores enteros, entonces sería utilizar de esta manera:
import qualified Data.MemoCombinators as Memo
foo = iterate step (Memo.integral f0, Memo.integral g0)
Si es necesario, se podría memoise la salida de cada paso también
step (f,g) = (Memo.integral (newF f g), Memo.integral (newG f g))
Espero que no vea esto como una ruptura de todo el programa.
En respuesta a su comentario:
Esto es lo mejor que puedo llegar a. No se ha probado, pero debería funcionar en la línea correcta.
Me preocupa que la conversión entre Double
Rational
y es innecesariamente ineficaz --- si había una instancia Bits
para Double
podríamos utilizar Memo.bits
lugar. Por lo tanto, esto podría no ser útil para ti en última instancia.
import Control.Arrow ((&&&))
import Data.Ratio (numerator, denominator, (%))
memoV :: Memo.Memo a -> Memo.Memo (V a)
memoV m f = \(V x y z) -> table x y z
where g x y z = f (V x y z)
table = Memo.memo3 m m m g
memoRealFrac :: RealFrac a => Memo.Memo a
memoRealFrac f = Memo.wrap (fromRational . uncurry (%))
((numerator &&& denominator) . toRational)
Memo.integral
Un enfoque diferente.
Tienes
step :: (V Double -> V Double, V Double -> V Double)
-> (V Double -> V Double, V Double -> V Double)
¿Qué cambia eso a
step :: (V Double -> (V Double, V Double))
-> (V Double -> (V Double, V Double))
step h x = (r fx gx, s fx gx)
where (fx, gx) = h x
y también cambiar
foo = (fst . bar, snd . bar)
where bar = iterate step (f0 &&& g0)
Esperemos que la compartían fx
y gx
debería resultar en un poco de velocidad -arriba.
Volver a calcular la n'th 'f' repetidamente no vuelve a calcular el (n-1) 'th' f' repetidamente ... pero recuerde, volver a calcular una función no significa lo mismo que volver a calcular el resultado de una llamada una función con un argumento! –