I’m trying to define a function like this, but something is wrong, and I don’t know why.
nomultiplon :: Int -> [a]
nomultiplon n = [x | x<- [1…1000], x mod
n /= 0]
I’m trying to define a function like this, but something is wrong, and I don’t know why.
nomultiplon :: Int -> [a]
nomultiplon n = [x | x<- [1…1000], x mod
n /= 0]
Assuming this is your code:
nomultiplon :: Int -> [a]
nomultiplon n = [x | x <- [1..1000], x `mod` n /= 0]
The function signature says that the function returns [a]
, a list of any values, but the function returns only whole numbers; it can’t return characters or boolean values; and the compiler complains about it.
Note that a
is not a generic type or template parameter as in other languages. it is not a placeholder for any type. a
is some type we know nothing about. If we don’t know anything about the type, we can’t do anything with it, so we can’t call mod
and it can’t represent a numeric value since the compiler can’t ensure that a
is number.
So how does the compiler know. In the function you define a variable x
, and since it is the variable returned by the function, it should be of type a
. After that you call mod x n
. Here is the signature of mod
:
mod :: Integral b => b -> b -> b
mod
takes two parameters of type b
where b
is an integral type. But your variable x
is of some type a
, so the compiler doesn’t know if a
is an integral type or not and rejects the code.
Now as the second parameter you apply n
to mod
. n
has the type Int
and Int
is an integral type. Because mod
takes 2 b
s and returns a b
, and n
is an Int
, the compiler can infer that b
is an Int
. and the type of mod
becomes:
mod :: Int -> Int -> Int
And it doesn’t work with a
as well since the compiler doesn’t know whether a
is an Int
or not.
Since both, x
and n
are applied to mod
and become b
in the mod
signature, they should have the same type and be instances of Integral
, so we get:
nomultiplon :: Int -> [Int]
nomultiplon n = [x | x <- [1..1000], x `mod` n /= 0]
or more generic:
nomultiplon :: Integral a => a -> [a]
nomultiplon n = [x | x <- [1..1000], x `mod` n /= 0]
Thank you very much for the exhaustive and clear explanation.