Confusion about data types in Haskell - haskell

I have to write a simple pi approximation and I did and it works fine, but in the task it says to write a function with the header "pi_approx :: Int -> Double".
My code:
pi_approx x = sqrt (pi2_approx(x))
pi2_approx x =
if x/= 1
then (6 /(x*x)) + (pi2_approx(x-1))
else (6/(1*1))
However my function works fine without "pi_approx :: Int -> Double", but when i try to use this declaration I always get the type error:
pi_approx.hs:10:14: error:
Couldn't match expected type Double' with actual type Int'
In the expression: (+) (6 / (x * x)) (pi2_approx (x - 1))
In the expression:
if x /= 1 then
(+) (6 / (x * x)) (pi2_approx (x - 1))
else
(6 / (1 * 1))
In an equation for `pi2_approx':
pi2_approx x
= if x /= 1 then
(+) (6 / (x * x)) (pi2_approx (x - 1))
else
(6 / (1 * 1))
|
10 | then (+) (6 /(x*x)) (pi2_approx(x-1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I tried to use fromIntegral in various ways and if I run the function without declaration I checked the type of the solution, which is: "(Floating a, Eq a) => a"
As I understand Double should be an instance of Floating so I don´t understand why it wont compile.
I am very new at haskell and it seems I don´t understand the core concept of data types and constraints. I can´t seem to find any simple and good documentation/explanation on the topic though. Maybe someone here can help me understand based on this example :)

because x is an Int, hence x * x is also an Int, and you can not use an Int for (/) :: Floating a => a -> a -> a.
You need to convert this to a Double, for example with fromIntegral :: (Integral a, Num b) => a -> b:
pi2_approx :: Int -> Double
pi2_approx 1 = 6
pi2_approx x = 6 / fromIntegral (x*x) + pi2_approx (x-1)
For a large number of iterations, it gives a result close to π2:
Prelude> sqrt (pi2_approx 10000)
3.1414971639472147

Related

Can you use `fromIntegral` to solve this type error?

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

Function type mismatch

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

Parse Error In Pattern for Recursive Mathematical Operators [duplicate]

This question already has an answer here:
Haskell (n+1) in pattern matching
(1 answer)
Closed 6 years ago.
I am a student learning Haskell. My textbook gives the following as an example:
(*) :: Int -> Int -> Int
m * 0 = 0
m * (n + 1) = m + (m * n)
It then asks us to redefine the ^ (positive integral exponentiation) operator in the same manner for an exercise. I assumed the following would work:
(^) :: Int -> Int -> Int
m ^ 0 = 1
m ^ (n + 1) = m * (m ^ n)
However, it fails to compile, giving a 'parse error in pattern' on the (n + 1) bit. Out of curiosity, I tried the multiplication operator as defined in the book's example, and it gave the same error.
Where/how is the textbook wrong, and how do I correct it?
Edit
Thank you to those who pointed out that this issue was addressed some years ago. Since the "feature" of n+k pattern matching was removed, how would I modify the textbook example to follow modern good practice?
In short, I now know why the original does not work, but how could it be changed to work?
You just replace n with n-1 on both sides of the equation:
(*) :: Int -> Int -> Int
m * 0 = 0
m * ((n-1) + 1) = m + (m * (n-1))
which is not valid syntax, but of course "simplifies" to the correct version
(*) :: Int -> Int -> Int
m * 0 = 0
m * n = m + (m * (n-1))
If you prefer not using the NPlusKPatterns extension then you can write:
import Prelude hiding ((^))
(^) :: Int -> Int -> Int
m ^ 0 = 1
m ^ n = m * (m ^ (n - 1))
The line import Prelude hiding ((^)) avoids the duplicate definition of (^), since it is already defined in Prelude.

Instance of Fractional Int required for definition

time :: Int -> (Int,Int,Int)
time x = ((x/3600),(x`mod`3600)/60,((x`mod`3600)`mod`60))
Instance of Fractional Int required for definition of time
expample =
time x = (hours, minutes, seconds)
time 3600 = (1,0,0)
given a time in seconds, must show it like this (hours, minutes, seconds) in the example 3600 is 1h 0m 0s
I believe you are getting that error because you are using the / operator with Int arguments. You can use div to get rid of the error, like so:
time :: Int -> (Int,Int,Int)
time x = ((x `div` 3600),(x `mod` 3600) `div` 60,((x `mod` 3600) `mod` 60))
As others have pointed out, (/) requires arguments to be Fractional whereas div is happy with Integral values.
You can't use the normal division operator on integers. This is true in mathematics and in Haskell, because division only works when the mathematical structure is a Field. The integers do not have division defined, but you can perform something similar called integer division (yes, a misleading name) or truncated division. This is achieved in Haskell using the div function, and you can use it as:
time :: Int -> (Int, Int, Int)
time x = (x `div` 3600, (x `mod` 3600) `div` 60, (x `mod` 3600) `mod` 60)
Here I've simply replaced each instance of / with div in its infix form, with no change to your algorithm otherwise.
So what does it mean for a type to implement the / operator? If we load up GHCi:
> :info (/)
class Num a => Fractional a where
(/) :: a -> a -> a
...
-- Defined in 'GHC.Real'
infixl 7 /
This tells us that / is a member of the Fractional typeclass, and anything that implements it must also implement the Num typeclass. Put simply, things that can be divided have to be fractional numbers. What else is in the Fractional typeclass?
> :info Fractional
class Num a => Fractional a where
(/) :: a -> a -> a
recip :: a -> a
fromRational :: Rational -> a
instance Fractional Float
instance Fractional Double
So Fractional numbers have division, a reciprocal operation, and a conversion from a Rational number. Ideally, a * recip a == a / a == 1, since this is true of our familiar fractional sets (rationals, reals, complex numbers).
The reason it's showing you the error is because (/) has the following type:
λ> :t (/)
(/) :: Fractional a => a -> a -> a
So, it accepts and returns only fractional numbers such as Float and Double. One way of solving this problem would be by using div function which has a type of div :: Integral a => a -> a -> a.
time x = ((x `div` 3600),(x`mod`3600) `div` 60,((x`mod`3600)`mod`60))
Another way to solve this problem would be to use the fromIntegral function on the number which will be applied to the / function and do the proper type conversion while returning:
time :: Int -> (Int, Int, Int)
time x = (a,b,c)
where a = ci $ fi x / fi 3600
b = ci $ fi (x `mod` 3600) / fi 60
c = (x `mod` 3600) `mod` 60
fi = fromIntegral
ci = ceiling

Haskell - Instance of Integral Float required for definition of unSum x = (y + y`mod`2 + 2) / 2 where y = x*(x+1) / 2

The Following code:
unSum :: Float -> Float
unSum x = (y + y`mod`2 + 2) / 2
where
y = x*(x+1) / 2
gives me this error when I try to load it into WinHugs 98:
Hugs> :load "D:\\kram\\unSumme2.hs"
ERROR file:.\unSumme2.hs:2 - Instance of Integral Float required for definition of unSumme2
What's the essence of this and how am I to do it? Anyway, I dont now if it serves my porpuse, I want to calculate the sum of the uneven numbers until x without recursivity.
It's because you're using mod. The definition of mod, from the Standard Prelude:
class (Real a, Enum a) => Integral a where
[...]
div, mod :: a -> a -> a
[...]
n `mod` d = r where (q,r) = divMod n d
In other words, it expects a to be of the numeric typeclass Integral, which includes only whole numbers.
If you want to stick with Floats, try using mod', from Data.Fixed, per this answer.
Alternatively, if you just want to do integer division, you could change your function's signature to
unSum :: Int -> Int
or similar.

Resources