I have following code, implmenting inverse function calculation, basing on this formulas:
derivation :: (Fractional a) => (a -> a) -> (a -> a)
derivation f = \ x -> ( ( f (x + dx) - f (x) ) / dx ) where dx = 0.1
evalA k f
| k == 0 = \x -> x
| otherwise = \x -> (derivation (evalA (k-1) f) x) / (derivation f x)
inverseFun f x =
let
x0 = 3.0
eps = 0.001
iter k prev sum =
let
elemA = evalA k f x0
elemB = prev * (x - (f x0)) / (if k == 0 then 1 else k)
newItem = elemA * elemB
in
if abs (newItem) < eps
then sum
else iter (k + 1) elemB (sum + newItem)
in
iter 0 1.0 0.0
f1 = \x -> 1.0 * x * x
main = do
print $ inverseFun f1 2.5
I need to optimise it by moving evalA
inside the inverseFun
and store previous step calculation A'n/F' to reuse it on the next iteration, if possible. As far as I understand, each time evalA
returns some sort of function and x applies afterwards, right before declaring elemA
.
How can I convert my evalA
or rewrite it to store previous results (by passing these results in iter
, obviously)?
Don't mind if this calculations are not too precise, it requires good x0
and eps
choice. My main question is in lambda conversion.
If you change your definition of inverseFun
such that the (if k == 0 then 1 else k)
is instead fromIntegral (if k == 0 then 1 :: Int else k)
, then you can provide type signatures to all of your functions:
derivation :: (Fractional a) => (a -> a) -> a -> a
evalA :: (Fractional a) => Int -> (a -> a) -> a -> a
inverseFun :: (Fractional a, Ord a) => (a -> a) -> a -> a
f1 :: (Fractional a) => a -> a
Which certainly helps out.
This is actually important for my solution to your problem, since we need k
to be an Int
, and you've used it as a Fractional a => a
. The fromIntegral
fixes that, but it needs to know that it's an Int
, so I just added the inline type signature to help the compiler along.
Since your function only depends on the previous single value, you can use our handy friend from Prelude
, iterate :: (a -> a) -> a -> [a]
. This applies a function over and over again, producing an infinite list of values. We can then index it at any point to get the desired result (this is why having k
an Int
is important!).
Our function will look like
evalA :: Fractional a => Int -> (a -> a) -> a -> a
evalA k f = iterate go id !! k
where
go = ???
Here id
is the same as your base case of \x -> x
, just shorter and with more optimization rules. It serves as the initial value for generating this list. To implement go
, the actual computation, we need it to accept the previous result as its argument:
where
go prev = \x -> derivation prev x / derivation f x
But this is considered "poor style" by hlint
, and so it is suggested to convert this to the form
where
go prev x = derivation prev x / derivation f x
And that's it! I tested it and got the exact same result for your example input. The full code can be viewed here.