Haskell type errors
I am really new to Haskell and this gives me ample time. I tried to write a basic function like "linspace" in Matlab, but the compiler seems to reject the idea that "gender" creates an Integral type. My code:
linspace :: Double -> Double -> Double -> [Double]
linspace x dx y
| y' == y = [x + i * dx | i <- nums]
| otherwise = ([x + i * dx | i <- nums] ++ [y])
where
n = floor ((y - x) / dx)
nums = [0..n]
y' = (x + (fromIntegral n) * dx)
What is causing the error in ghci:
maths.hs:8:21: error:
* No instance for (Integral Double) arising from a use of `floor'
* In the expression: floor ((y - x) / dx)
In an equation for `n': n = floor ((y - x) / dx)
In an equation for `linspace':
linspace x dx y
| y' == y = [x + i * dx | i <- nums]
| otherwise = ([x + i * dx | i <- nums] ++ [y])
where
n = floor ((y - x) / dx)
nums = [0 .. n]
y' = (x + (fromIntegral n) * dx)
maths.hs:10:28: error:
* No instance for (Integral Double)
arising from a use of `fromIntegral'
* In the first argument of `(*)', namely `(fromIntegral n)'
In the second argument of `(+)', namely `(fromIntegral n) * dx'
In the expression: (x + (fromIntegral n) * dx)
Failed, modules loaded: none.
Any help would be greatly appreciated!
source to share
This version compiles:
linspace :: Double -> Double -> Double -> [Double]
linspace x dx y
| y' == y = [x + (fromIntegral i) * dx | i <- nums]
| otherwise = ([x + (fromIntegral i) * dx | i <- nums] ++ [y])
where
n = toInteger $ floor ((y - x) / dx)
nums = [0..n]
y' = (x + (fromIntegral n) * dx)
What are the changes?
-
As @Alec commented, while
floor
logically is an integer, it is not. You need to usetoInteger
. -
After that you need to use
fromIntegral
when multiplyingi
and `dex.
source to share
You bound the result linspace
to [Double]
because of the type annotation. Therefore [x + i * dx | i <- nums]
should create such a list Double
s. x
and dx
should be Double
as they are parameters passed to the function, which are all declared as Double
. But what about i
? It is related to nums
; to i
be Double
, nums
must be [Double]
.
The numbers are defined as
nums = [0..n]
Ok nums
- the list is in order. But a list of what? It depends on n
; let's get a look!
n = floor ((y - x) / dx)
floor
takes, in a nutshell, yours Double
and creates Integral
. Therefore nums
, this is a list of integrals. This is the error you are getting: there is no instance Integral
for Double
; there is no way for types to work well.
To fix these errors, you must do n
a Double
:
n = fromIntegral $ floor ((y - x) / dx)
So your definition y'
must be changed as well:
y' = x + n * dx
In a nutshell
linspace :: Double -> Double -> Double -> [Double]
linspace x dx y
| y' == y = [x + i * dx | i <- nums]
| otherwise = ([x + i * dx | i <- nums] ++ [y])
where
n = fromIntegral $ floor ((y - x) / dx)
nums = [0.. n]
y' = (x + n * dx)
source to share