Reputation: 36404
I'm getting an error:
No instance for (Integral [t0])
when I run this haskell code.
boomBangs xs = [(a,b,c) |a<-[1..xs],b<-[1..xs],c<-[1..xs], xs <- xs `div` 2]
Where am I going wrong?
Upvotes: 1
Views: 258
Reputation: 55039
What you said was:
Give me a tuple of
a
,b
, andc
:[ (a, b, c)
For each
a
,b
, andc
in the list of values from1
toxs1
:| a <- [1..xs1] , b <- [1..xs1] , c <- [1..xs1]
For each
xs2
in the quotient ofxs1
and 2., xs2 <- xs1 `div` 2 ]
If you compile with warnings enabled (-Wall
) or turn them on in GHCi (:set -Wall
) then you’ll get a warning that the xs
in xs <- ...
shadows the xs
in boomBangs xs = ...
, and also that it’s unused. Obviously this kind of warning can be very helpful, as it points right to your problem.
Since xs1
is the input to your function, you end up with a type like this:
(Integral [t]) => [t] -> [([t], [t], [t])]
Which is to say that the function takes a list (xs1
) that can act as a number ((`div` 2)
) and gives you back a list of tuples of such lists. Even though you’re trying to divide a list by a number, GHC allows it and infers a more general type because you could have defined an Integral
instance for lists. It only discovers that you haven’t when you actually try to use the function on a concrete type. Writing down type signatures can help keep the compiler grounded and give you better error messages.
I can only guess you meant for boomBangs
to have a type like:
Integral t => [t] -> [(t, t, t)]
Or just:
[Int] -> [(Int, Int, Int)]
In which case maybe you were thinking of something like this:
[ (a, b, c)
| x <- xs
, a <- [1..x `div` 2]
, b <- [1..x `div` 2]
, c <- [1..x `div` 2]
]
Upvotes: 6
Reputation: 68152
The problem is that you're trying to divide a list. In particular, xs `div` 2
is the incorrect expression.
You can get this from the error message: it's complaining that [t0]
does not behave like an integer (e.g. it isn't in the Integral
class). [t0]
is just a list of stuff--the t0
, being in lowercase, is a type variable that represntes any type.
Since lists of stuff aren't numbers, we can't really know how to divide them.
You can see why you get this exact error message by looking at the type of div
:
div :: Integral i => i -> i -> i
All this means is that given some type i
in the Integral
class, you can divide two of them together to get a third. Since lists of things are not part of the integral class, you can't divide them and so you get an error.
If div
had a concrete type like div :: Int -> Int -> Int
, you would get an error telling you that it can't match the expected type Int
with the actual type [t0]
. However, since the type actually contains a variable i
, the error is a bit more complex: [t0]
cannot be a valid type to use in place of i
because it is not in the Integral
class.
Upvotes: 6