2
votes

Trying a couple different ways of implementing Newtons Method, but I cant seem to get it working. It's most likely a very simple fix, but I just need someone to point out what I'm doing wrong. Yeah I know my code is ugly, just messing around right now.

In this example, I just try to make an equation for xn+1, which isn't working.

function :: (Num a) => a ->  a
function x = 98 - x^98
function' :: (Num a) => a -> a
function' x = (-98)*(x^97)
xi = 1.04
iterations = 20

newtons :: (Integral a) => a -> a

newtons x = x - fromIntegral ( div (function x) (function' x) )

When I type 'newtons xi' in ghci I get an error that says "no instance for Integral Double arising from a use of newtons". What type class should I be using to make this work?

1
Why would you implement an archetypical calculus, i.e. real number based algorithm with integer arithmetic? This is obviously a case for floating-point numbers. - leftaroundabout
The problem is that xi is a Double, but you're passing it in to newtons, which expects an Integral a type. Double is not an Integral type. Why are you converting to Integral anyway? It has no relevance in the context of Newton's method. - bheklilr
Forgot I had that there. But when I made my type class for Newtons (Num a) it told me "Could not deduce (Integral a) arising from a use of div from the context of (Num a) bound by the type signature for newtons" So I assumed that div must only work on integers. - caleborp
That's because of the type signature of div. You probably need to use Fractional rather than Num, since then you can use /. - bheklilr

1 Answers

2
votes

Just needed more general types. Didn't see the iteration function which is the core of the algorithm so I tried to adapt it around your existing code:

function :: Num a => a -> a
function x = 98 - x^98

function' :: Num a => a -> a
function' x = (-98)*(x^97)

xi :: Double
xi = 1.04

newton :: (Fractional a, Ord a) => (a -> a) -> (a -> a) -> a -> a
newton f f' x
    | (abs (f x)) < epsilon = x
    | otherwise = newton f f' (x - (f x / f' x))
  where
    epsilon = 1e-4

main :: IO ()
main = do
  -- Prints out the two extrema
  print $ newton function function' xi    --  1.0478970878235732
  print $ newton function function' (-xi) -- -1.0478970878235732

This is a naive implementation, if you need performance and numeric stability then the ad package is best suited for this.