Reputation: 1003
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.
Upvotes: 2
Views: 121
Reputation: 54058
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.
Upvotes: 3