So I just started learning haskell and I'm trying to use this if statement:
[if (((mod x 3) == 0) && ((mod x 5) == 0)) then "Fizzbuzz" else x | x <- [1..50]]
but when I compile in ghci I get the following error:
No instance for (Integral [Char])
arising from a use of `mod' at baby.hs:22:19-25
Possible fix: add an instance declaration for (Integral [Char])
In the first argument of `(==)', namely `(mod x 3)'
In the first argument of `(&&)', namely `((mod x 3) == 0)'
In the expression: (((mod x 3) == 0) && ((mod x 5) == 0))
Failed, modules loaded: none.
Ok, so I've figured out that x is inferred to be a string because the if is returning an explicit string, therefore this entire function wouldn't work. S开发者_开发技巧o how would I actually solve this problem? (I know my question is dumb, but I'm not used to ether the functional paradigm or having static typing with type inference).
The 'then' and 'else' branches must have the same type. "Fizzbuzz"
is a string where-as x
is an Int. If you're just going to print the result then just put show x
for your else
branch.
Perhaps this would be good to add to the if/then/else section of Haskell's common misunderstandings. For the same reason the else
branch must exist, it also must have the same type as the then
.
The problem is not in this part of the code. The error message is about the type of mod being mod :: (Integral a) => a -> a -> a
, but x supposedly being of type [Char].
I am guessing that the type of x is being inferred here (since the type should be Int). Therefor in order to debug the problem I suggest you declare the type of your functions, like this:
f :: Int -> ...
f x ... = if (((mod x 3) == 0) && ((mod x 5) == 0))...
If you still have a problem, post the rest of the code.
All you really have to do is add show in order to convert your Int into a String.
[if mod x 3 == 0 && mod x 5 == 0 then "Fizzbuzz" else show x | x <- [1..50]]
wich in turn can be written as:
map (\x -> if mod x 15 == 0 then "Fizzbuzz" else show x) [1..50]
main = mapM_ (putStrLn . fb) [1..100]
fb :: Int -> String
fb x | [3,5] `divides` x = "fizzbuzz"
| [5] `divides` x = "buzz"
| [3] `divides` x = "fizz"
| otherwise = show x
divides :: [Int] -> Int -> Bool
xs `divides` y = y `mod` product xs == 0
From the looks of it, you are trying to solve ProjectEuler's problem 1. Try to use the "mod" function in its infix form, i.e. like this :
if ((x `mod` 3 == 0) && (x `mod` 5 == 0)) then blah blah
I think this will force the compiler to think that x is going to be an Int. Otherwise, you'll have to provide us with more info, like KennyTM, luqui and TomMD proposed (maybe the error is somewhere else down the line)!
精彩评论