 # Probably too easy, but I can't find the problem

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]

``````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]
``````
8 Likes

Thank you very much for the exhaustive and clear explanation.

2 Likes