我的问题怎么了?

时间:2011-02-25 06:18:42

标签: haskell

所以我刚开始学习haskell,我正在尝试使用这个if语句:

[if (((mod x 3) == 0) && ((mod x 5) == 0)) then "Fizzbuzz" else x | x <- [1..50]]

但是当我在ghci中编译时,我收到以下错误:

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.

好的,所以我发现x被推断为一个字符串,因为if返回一个显式字符串,因此整个函数不起作用。那我怎么能真正解决这个问题呢? (我知道我的问题是愚蠢的,但我不习惯使用功能范例或使用类型推断进行静态输入)。

5 个答案:

答案 0 :(得分:7)

'then'和'else'分支必须具有相同的类型。 "Fizzbuzz"是一个字符串,其中x是Int。如果您打算打印结果,只需将show x放入else分支。

也许最好添加到Haskell的common misunderstandings的if / then / else部分。出于同样的原因,else分支必须存在,它也必须与then具有相同的类型。

答案 1 :(得分:4)

问题不在于此部分代码。错误消息是关于mod的类型mod :: (Integral a) => a -> a -> a,但x应该是[Char]类型。

我猜这里推断出x的类型(因为类型应该是Int)。因此,为了调试问题,我建议您声明函数的类型,如下所示:

f :: Int -> ...
f x ... = if (((mod x 3) == 0) && ((mod x 5) == 0))...

如果您仍有问题,请发布其余代码。

答案 2 :(得分:2)

您只需添加show即可将Int转换为String。

[if mod x 3 == 0 && mod x 5 == 0 then "Fizzbuzz" else show x | x <- [1..50]]
反过来可以写成:

map (\x -> if mod x 15 == 0 then "Fizzbuzz" else show x) [1..50]

答案 3 :(得分:-1)

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

答案 4 :(得分:-3)

从它的外观来看,你正在尝试解决ProjectEuler的问题1.尝试以其中缀形式使用“mod”函数,即如下:

if ((x `mod` 3 == 0) && (x `mod` 5 == 0)) then blah blah

认为这将迫使编译器认为x将成为Int。否则,您将不得不向我们提供更多信息,例如KennyTM,luqui和TomMD建议(可能错误是在其他地方)!