Reputation: 61520
I am trying to write a function that computes ex (for the first 10 terms) given an integer `x.
The series expansion for ex is given by
1 + x + x2/2! + x3/3! + x4/4! + ....
The function itself was fairly easy to write, but I can't seem to understand Haskell type rules for division, i.e I want to divide an integer by a larger integer and get a floating-point result:
Here is what I have so currently
_eToX :: (Fractional a, Integral a) => a -> a -> a
_eToX x 0 = 1.0
_eToX x 1 = x
_eToX x n = ( fromIntegral(x^n) / fromIntegral(factorial n) ) + _eToX x (n - 1)
What I am doing above here makes sense to me, compute two integer results (x^n
and factorial n
) then evaluate them in a Floating point context using fromIntegral
and /
. This function however returns this error:
1. Could not deduce (a ~ Integer)
from the context (Fractional a, Integral a)
bound by the type signature for
_eToX :: (Fractional a, Integral a) => a -> a -> a
at /run-r4AWbVU9Fyph0OVhK3Dm/solution.hs:9:10-50
`a' is a rigid type variable bound by
the type signature for
_eToX :: (Fractional a, Integral a) => a -> a -> a
at /run-r4AWbVU9Fyph0OVhK3Dm/solution.hs:9:10
In the return type of a call of `factorial'
In the second argument of `(/)', namely `factorial n'
In the first argument of `(+)', namely `(x ^ n / factorial n)'
2. No instance for (Integral Double) arising from a use of `f'
Possible fix: add an instance declaration for (Integral Double)
In the expression: f
In the second argument of `($)', namely
`f $ map (read :: String -> Double) $ lines inputdata'
In the second argument of `($)', namely
`map show $ f $ map (read :: String -> Double) $ lines inputdata'
I am running the function with this main function:
main = do
n <- readLn :: IO Int -- n doesnt really matter here because of getContents
inputdata <- getContents
mapM_ putStrLn $ map show $ f $ map (read :: String -> Double) $ lines inputdata
Upvotes: 1
Views: 263
Reputation: 501
Is your f
the given _eToX
? your _eToX takes two arguments but you apply f to only one.
This is fine as long as you only want a a partial application.
Concerning the error messages you should check the following:
What is the type of your factorial it seems to be something that has an Integer as an result and not something that implements the Typclasses Integral
and fractional
You added a type annotation for your read function, s.t. it returns a Double
Which is not an instance of Integral
. But your f
seems to take something as an argument which is an instance of Integral
.
Upvotes: 0
Reputation: 28097
This type:
_eToX :: (Fractional a, Integral a) => a -> a -> a
doesn't make sense. You want the first argument and result to be Fractional
, but the second argument, corresponding to the sequence position, should be Integral
. Change the type to:
_eToX :: (Fractional a, Integral b) => a -> b -> a
Now there's a different error, arising from a missing Integral
instance because of fromIntegral (x^n)
. ghci shows
Prelude> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
So it's not necessary to even use fromIntegral
here, as the output is already the correct type. The final function is:
_eToX :: (Fractional a, Integral b) => a -> b -> a
_eToX x 0 = 1.0
_eToX x 1 = x
_eToX x n = ( (x^n) / fromIntegral(factorial n) ) + _eToX x (n - 1)
Upvotes: 4
Reputation: 3766
Here is what you are probably looking for.
eToX :: Integral a => Double -> a -> Double
eToX x 0 = 1
eToX x 1 = 1 + x
eToX x n = x^^n / (fromIntegral $ factorial n) + eToX x ( n - 1)
(^^) :: (Fractional a, Integral b) => a -> b -> a
You didn't want n
and x
to be the same. See how that power function does it.
Oh, and your equation was wrong for n = 1
you should have 1 + x
Upvotes: 0