1

i'm trying to implement newtons method in haskell, but i'm ending every time in a "Stackoverflow" Exception.. I spent a lot of time and got no solution .. -.-

data Term = Monom(Integer, Integer)
            | Add(Term, Term)
            | Mul(Term, Term)
            | Div(Term, Term);

iterate :: (a -> a) -> a -> [a]
iterate f a0 = a0 : (Main.iterate f (f(a0)))

stop1 :: Float -> [Float] -> Float
stop1 eps (a1 : (a2:as))
  | abs(a1-a2) < eps = a2
  | otherwise = stop1 eps (a2:as)

step1 :: Term -> Float -> Float
--step1 f f' a = a - (f a) / (f' a)
step1 f a = a - (eval f a) / (eval (diff f) a)

--newton :: (Float -> Float) -> (Float -> Float) -> Float -> Float -> Float
newton :: Term -> Float -> Float -> Float
newton f a0 eps = stop1 eps (Main.iterate (step1 f) a0)

quadrieren (Monom(a,b)) = Monom(a*a, b*b)

diff :: Term -> Term
diff (Monom(a,b)) = if b>0 then Monom(a*b, b-1) else Monom(0,0)                
diff (Add(x,y)) = Add(diff(x), diff(y))                                        
diff (Mul(x,y)) = Add(Mul(diff(x), y), Mul(diff(y), x))                        
diff (Div(x,y)) = Div(Add(Mul(diff(x), y), Mul(diff(y), x)), quadrieren(y)) 

eval :: Term -> Float -> Float
eval (Monom(a,b)) f = (evalMonom (Monom(a,b)) f)
eval (Add(Monom(a,b), Monom(c,d))) f = (evalMonom (Monom(a,b)) f) + (evalMonom (Monom(c,d)) f)
eval (Mul(Monom(a,b), Monom(c,d))) f = (evalMonom (Monom(a,b)) f) * (evalMonom (Monom(c,d)) f)
eval (Div(Monom(a,b), Monom(c,d))) f = (evalMonom (Monom(a,b)) f) / (evalMonom (Monom(c,d)) f)

evalMonom :: Term -> Float -> Float
evalMonom (Monom(a,b)) x = fromInteger(a) * fromInteger(pow (toInt(x)) b)

pow :: Integer -> Integer -> Integer 
pow x 0 = 1
pow x n = x * pow x (n-1)

toInt :: Float -> Integer
toInt x = round x

I assume that the problem could be in the pow function, but i'm not sure.. Thanks in advance for every help!

MaMa
  • 31
  • 4
  • I haven't gone through all the code, but `pow a b` is likely to throw that exception when `b < 0` – iamwhoiam Jul 12 '17 at 12:04
  • `pow a b` will absolutely end up in an infinite recursion if it is ever called with `b < 0`... you could try to catch this case and just give the answer you can interpret to check if this is what is going on... – Chris Jul 12 '17 at 12:09
  • 2
    Why would you implement `pow` yourself in the first place, anyway? Use [`^`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:-94-) which does the exact same thing (just faster, for large-ish exponents) if `n` is positive, and doesn't diverge when it's negative. – leftaroundabout Jul 12 '17 at 12:09
  • 3
    Also show _how_ you've encountered that problem. There is no example. – Zeta Jul 12 '17 at 13:39
  • @leftaroundabout: changing pow to ^ says "No instance for (Integral Float) arising from a use of ^" – MaMa Jul 12 '17 at 14:12
  • No, you really shouldn't need all those type conversions; in particular, rounding the argument to `eval` is clearly wrong for this application. Declare `Monom` as `Monom Float Int`, then you can simply do `evalMonom (Monom a e) x = a * x^e`. – leftaroundabout Jul 12 '17 at 14:18
  • Thanks for your help! Problem has been solved by replacing the pow function with ^ =) – MaMa Jul 12 '17 at 15:05
  • Next time you should also tell how you're running / compiling: using ghci or compiling with ghc using optimizations? – jberryman Jul 12 '17 at 17:46
  • Please take your time to read [How to ask](https://stackoverflow.com/help/how-to-ask) – wizzup Jul 13 '17 at 07:31

0 Answers0