Data.MemoCombinatorsが便利な場合があります(data-memocombinatorsパッケージに含まれています)。
あなたはどの引数があなたf
をタイプし、g
取るかを言わない---それらが両方とも整数値をとるなら、あなたはそれを次のように使うだろう:
import qualified Data.MemoCombinators as Memo
foo = iterate step (Memo.integral f0, Memo.integral g0)
必要に応じて、各ステップの出力をメモ化することもできます
step (f,g) = (Memo.integral (newF f g), Memo.integral (newG f g))
これがプログラム全体をバラバラにするものと見なされないことを願っています。
あなたのコメントへの返信:
これは私が思いつくことができる最高です。テストされていませんが、正しい方向に機能しているはずです。
Double
との間の変換Rational
が不必要に非効率的であるのではないかと心配しています---代わりに使用できるBits
インスタンスがあった場合。したがって、これは最終的には実際には役に立たない可能性があります。Double
Memo.bits
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
別のアプローチ。
あなたが持っている
step :: (V Double -> V Double, V Double -> V Double)
-> (V Double -> V Double, V Double -> V Double)
それをに変更するのはどうですか
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
そしてまた変化する
foo = (fst . bar, snd . bar)
where bar = iterate step (f0 &&& g0)
うまくいけば、共有さfx
れgx
、少しスピードアップするはずです。