I have the following code which uses Newton's method to approximate the square root of some number. The problems is that when I run it, I get an error..What is wrong and how can I fix it?
newtonRootSequence :: Double -> [Double]
newtonRootSequence d = newtonSequenceGenerator d 1
newtonSequenceGenerator :: Double -> Double -> [Double]
newtonSequenceGenerator d xn = nxplus1 : newtonSequenceGenerator d nxplus1
where nxplus1 = (xn + d / xn) / 2
newtonRoot:: Double -> Double -> Double
newtonRoot d epsilon = head ([xs !! index | index <- [1..((length xs) - 1)], (xs !! index) - (xs !! index - 1) <= epsilon]
where xs = newtonRootSequence d
Error:
<interactive>:2:1: error:
* No instance for (Show (Double -> Double))
arising from a use of `print'
(maybe you haven't applied a function to enough arguments?)
* In a stmt of an interactive GHCi command: print it
Running it should be like the following:
$newtonRoot 35
In Haskell all function are curryfied, so, your function
newtonRoot:: Double -> Double -> Double
the are "hidden parenthesis":
newtonRoot:: Double -> (Double -> Double)
if you provide one argument newtonRoot 35 you have
(newtonRoot 35) :: Double -> Double
and a function f :: Double -> Double is not instance of Show type class
You need to finally provide the last argument to your function value:
(newtonRoot 35 2) :: Double
Double can me shown
newtonRoot takes two arguments, a d and an epsilon. You didn't supply an epsilon. Try
> newtonRoot 35 0.1
instead.
There are other errors, too, but this should get you started down the debugging path.
Related
Would using fromIntegral help fix this type error I'm getting.
Couldn't match expected type ‘Float’ with actual type ‘Int’?
If not, how can I resolve it?
taxiFare :: Int -> Float
taxiFare x | x >= 10 = longRide
| otherwise = shortRide
where
longRide = 2.2 + (x * 0.3) + 2
shortRide = 2.2 + (x * 0.5)
The problem is that your signature specifies that x is an Int. But the result type should be a Float since calculations like (*) :: Num a => a -> a -> a and (+) :: Num a => a -> a -> a require the two operands and the result to be all of the same type, it thus means that x should be a Float.
You can make use of fromIntegral :: (Integral a, Num b) => a -> b to convert any Integral type to any Num type, so yes. You can define for example a variable that will store the Float counterpart of x and use that variable:
taxiFare :: Int -> Float
taxiFare x
| x >= 10 = longRide
| otherwise = shortRide
where longRide = 0.3 * xf + 4.2
shortRide = 0.5 * xf + 2.2
xf = fromIntegral x
The error now iCouldn't match expected type ‘Double’
with actual type ‘Double -> Double -> Double -> Double’ , Probable cause: ‘(+)’ is applied to too few arguments
In the expression: cubicQ ^ 3 + r ^^ 2
In an equation for ‘cubicDisc’: cubicDisc q r = cubicQ ^ 3 + r ^^ 2
cubicR :: Double -> Double -> Double -> Double -> Double
cubicR a b c d = (9*a*b*c-27*a^^2*d-2*b^^3)/(54*a^^3)
cubicQ :: Double -> Double -> Double -> Double
cubicQ a b c = (3*a*c-b^^2)/(9*a^^2)
cubicDisc :: Double -> Double -> Double
cubicDisc q r = cubicQ^3 + r^^2
cubicS :: Double -> Double -> Double
cubicS q r = (r + sqrt(q^^3+r^^2))**(1/3)
cubicT :: Double -> Double -> Double
cubicT q r = (r - sqrt(q^^3+r^^2))**(1/3)
cubicRealSolutions :: Double -> Double -> Double -> Double -> [Double]
cubicRealSolutions a b c d = if cubicDisc > 0 || root == 0
then [rootOne,rootTwo,rootThree]
else []
where
rootOne= (cubicS + cubicT) - b/(3*a)
rootTwo = (cubicS+cubicT)/2 -(b)/(3*a) + sqrt(3)/2*(cubicS-cubicT)
rootThree = (cubicS+cubicT)/2 -(b)/(3*a) + sqrt(3)/2*(cubicS-cubicT)
Syntactically, your program does not make sense, that's what the compiler is complaining about. First, the if statement is just floating around; its not in the same scope as cubicRealSolutions. I would recommend revising and reading through some Haskell documentation on let, if, and function syntax . For now, if I were you I would clean up the code as follows:
cubicRealSolutions :: Double -> Double -> Double -> Double -> [Double]
cubicRealSolutions a b c d = if cubicDisc > 0 || root == 0
then [rootOne,rootTwo,rootThree]
else []
where
root = 0
rootOne= (cubicS + cubicT) - b/(3*a)
rootTwo = (cubicS+cubicT)/2 -(b)/(3*a) + sqrt(3)/2*(cubicS-cubicT)
rootThree = (cubicS+cubicT)/2 -(b)/(3*a) + sqrt(3)/2*(cubicS-cubicT)
cubicDisc = 18*a*b*c*d - 4*(b^3)*d + (b^2)*(c^2) - 4*a*c^3 - 27*(a^2)*(d^2)
cubicS = 0.1
cubicT = 0.2
However, there are still major issues with this code and it will not compile because root,cubicDisc, cubicS, cubicT are not defined. Also, you never use the parameters c or d which I find odd, as you probably want to use them. Finally, if statements must evaluate to the same type, hence the else evaluates to an empty list instead of a string. Even my revision is not "good" style. There are too many statements in the where clause. If this happens its best to break the function down into smaller parts to avoid run-on where clauses. I've used ... to indicate what you need to define for the compiler.
References: LYAH
PS: Personally, I find where syntax to be easier to understand than let but that is up to personal style choices. Although, let is a bit more flexible than where.
EDIT: I have defined root, cubicS, and cubicT with placeholder values to illustrate that they must evaluate to a Double.
I have a function with function type :
newtonRootSequence' :: Double -> Double -> [Double]
and function definition:
newtonRootSequence' xn d = [(xn + (d * (1/xn))) div 2] ++ newtonRootSequence' ((xn + (d * (1/xn))) div 2) d
upon receiving two values xn and d it should calculate the results for the given function
[(xn + (d * (1/xn))) div 2]
But for some reason on launch the compilator is not accepting the function with an error:
Couldnt match expected type '(Integer->Integer->Integer->) ->Integer
->Double with actual type double the function (xn + (d * (1/xn))) div 2) is applied to two arguments
This error occurs to the part where I try to send the result of the equation into the recursive step
++ newtonRootSequence' ((xn + (d * (1/xn))) div 2) d
As already mentioned in the comments:
if you want to use div as an infix function, you have to enclose it in backticks
div is for integral division with truncation towards negative infinity, not for dividing Double
These two points are the cause for your error message.
To divide Doubles, use the / operator like you already did in your expression 1/xn.
With this your code should work. For clarity it could be transformed:
Extract the duplicated expression to compute the next xn in the sequence into a where clause. The expression can also be slightly simplified. Adding a single element in front of a list can simply be done with the cons operator (:):
newtonRootSequence' xn d = xn' : newtonRootSequence' xn' d
where xn' = (xn + (d / xn)) / 2
You could use iterate :: (a -> a) -> a -> [a] from the Prelude to separate the computation for a single step from the generation of the list of intermediate steps (note the flipped arguments):
sequenceStep :: Double -> Double -> Double
sequenceStep s xn = (xn + (s / xn)) / 2
newtonRootSequence' :: Double -> Double -> [Double]
newtonRootSequence' s x0 = iterate (sequenceStep s) x0
I have the following code which uses Newton's method to approximate the square root of some number. The problems is that when I run it, I get an error..What is wrong and how can I fix it?
newtonRootSequence :: Double -> [Double]
newtonRootSequence d = newtonSequenceGenerator d 1
newtonSequenceGenerator :: Double -> Double -> [Double]
newtonSequenceGenerator d xn = nxplus1 : newtonSequenceGenerator d nxplus1
where nxplus1 = (xn + d / xn) / 2
newtonRoot:: Double -> Double -> Double
newtonRoot d epsilon = head ([xs !! index | index <- [1..((length xs) - 1)], (xs !! index) - (xs !! index - 1) <= epsilon]
where xs = newtonRootSequence d
Error:
<interactive>:2:1: error:
* No instance for (Show (Double -> Double))
arising from a use of `print'
(maybe you haven't applied a function to enough arguments?)
* In a stmt of an interactive GHCi command: print it
Running it should be like the following:
$newtonRoot 35
In Haskell all function are curryfied, so, your function
newtonRoot:: Double -> Double -> Double
the are "hidden parenthesis":
newtonRoot:: Double -> (Double -> Double)
if you provide one argument newtonRoot 35 you have
(newtonRoot 35) :: Double -> Double
and a function f :: Double -> Double is not instance of Show type class
You need to finally provide the last argument to your function value:
(newtonRoot 35 2) :: Double
Double can me shown
newtonRoot takes two arguments, a d and an epsilon. You didn't supply an epsilon. Try
> newtonRoot 35 0.1
instead.
There are other errors, too, but this should get you started down the debugging path.
I've written some code that's meant to integrate a function numerically using the trapezoidal rule. It works, but the answer it produces has a wrong sign. Why might that be?
The code is:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (points (1000-1) h)
partial_sum = sum most_parts
points :: Double -> Double -> [Double]
points x1 x2
| x1 <= 0 = []
| otherwise = (x1*x2) : points (x1-1) x2
Trapezoidal rule
The code is probably inelegant, but I'm only a student of Haskell and would like to deal with the current problem first and coding style matters after that.
Note: This answer is written in literate Haskell. Save it with .lhs as extension and load it in GHCi to test the solution.
Finding the culprit
First of all, let's take a look at integration. In its current form, it contains only summation of function values f x. Even though the factors aren't correct at the moment, the overall approach is fine: you evaluate f at the grid points. However, we can use the following function to verify that there's something wrong:
ghci> integration (\x -> if x >= 10 then 1 else (-1)) 10 15
-4.985
Wait a second. x isn't even negative in [10,15]. This suggests that you use the wrong grid points.
Grid points revisited
Even though you've linked the article, let's have a look at an exemplary use of the trapezoidal rule (public domain, original file by Oleg Alexandrov):
Although this doesn't use a uniform grid, let's suppose that the 6 grid points are equidistant with grid distance h = (b - a) / 5. What are the x coordinates of those points?
x_0 = a + 0 * h (== a)
x_1 = a + 1 * h
x_2 = a + 2 * h
x_3 = a + 3 * h
x_4 = a + 4 * h
x_5 = a + 5 * h (== b)
If we use set a = 10 and b = 15 (and therefore h = 1), we should end up with [10, 11, 12, 13, 14, 15]. Let's check your points. In this case, you would use points 5 1 and end up with [5,4,3,2,1].
And there's the error. points doesn't respect the boundary. We can easily fix this by using pointsWithOffset:
> points :: Double -> Double -> [Double]
> points x1 x2
> | x1 <= 0 = []
> | otherwise = (x1*x2) : points (x1-1) x2
>
> pointsWithOffset :: Double -> Double -> Double -> [Double]
> pointsWithOffset x1 x2 offset = map (+offset) (points x1 x2)
That way, we can still use your current points definition to generate grid points from x1 to 0 (almost). If we use integration with pointsWithOffset, we end up with
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (pointsWithOffset (1000-1) h a)
partial_sum = sum most_parts
Tying up loose ends
However, this doesn't take into account that you use all inner points twice in the trapezoid rule. If we add the factors, we end up with
> integration :: (Double -> Double) -> Double -> Double -> Double
> integration f a b =
> h / 2 * (f a + f b + 2 * partial_sum)
> -- ^^^ ^^^
> where
> h = (b - a) / 1000
> most_parts = map f (pointsWithOffset (1000-1) h a)
> partial_sum = sum most_parts
Which yields the correct value for our test function above.
Exercise
Your current version only supports 1000 grid points. Add an Int argument so that one can change the number of grid points:
integration :: Int -> (Double -> Double) -> Double -> Double -> Double
integration n f a b = -- ...
Furthermore, try to write points in different ways, for example go from a to b, use takeWhile and iterate, or even a list comprehension.
Yes it indeed was the points plus you had some factors wrong (the inner points are multiplied by 2) - this is the fixed version of your code:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + innerSum) / 2
where
h = (b - a) / 1000
innerPts = map ((2*) . f . (a+)) (points (1000-1) h)
innerSum = sum innerPts
points :: Double -> Double -> [Double]
points i x
| i <= 0 = []
| otherwise = (i*x) : points (i-1) x
which gives sensible approximations (to 1000 points):
λ> integration (const 2) 1 2
2.0
λ> integration id 1 2
1.5
λ> integration (\x -> x*x) 1 2
2.3333334999999975
λ> 7/3
2.3333333333333335