帮助我理解这个Haskell(GHCI)类型错误:( Num [Char])将数字附加到字符串时

时间:2011-06-06 06:16:37

标签: haskell types ghci

本周末我一直在尝试学习Haskell,而且当我真正尝试编写递归函数(而不是仅仅从教程中输入一个)时,我得到了一个类型错误。

我非常感谢任何帮助理解(1)错误意味着什么(我不理解“修复”); (2)为什么会抛出错误 - 我很确定我没有对传递的类型犯任何错误。

我的代码:

tell :: (Show a) => [a] -> String  
tell'in :: (Show a, Num n) => [a] -> n -> String -> (n, String)
tell [] = "The list is empty"  
tell (x:[]) = "The list has one element: " ++ show x  
tell (x:xs) = "The list has " ++ n ++ " elements: " ++ s where (n, s) = (tell'in (xs) (1) (show x))  


tell'in (x:[]) n s = ((n + 1), (s ++ " and " ++ (show x)))
tell'in (x:xs) n s = tell'in xs (n+1)  (s ++ " and " ++ show x)

当我尝试将其加载到GHCI中时出现的错误:

[1 of 1] Compiling Main             ( example.hs, interpreted )

example.hs:13:88:
    Could not deduce (Num [Char]) arising from the literal `1'
    from the context (Show a)
      bound by the type signature for tell :: Show a => [a] -> String
      at example.hs:(11,1)-(13,99)
    Possible fix:
      add (Num [Char]) to the context of
        the type signature for tell :: Show a => [a] -> String
      or add an instance declaration for (Num [Char])
    In the second argument of `tell'in', namely `(1)'
    In the expression: (tell'in (xs) (1) (show x))
    In a pattern binding: (n, s) = (tell'in (xs) (1) (show x))
Failed, modules loaded: none.
Prelude>

3 个答案:

答案 0 :(得分:3)

tell'in正在返回Num n => n,然后您(++) String(又名[Char])在{{1}的最后一个等式中tell }}。您可能希望在那里使用show n而不是n

答案 1 :(得分:2)

tell'in的类型表示其返回值的第一个坐标与第二个参数的类型相同。在tell中,您使用数字作为其第二个参数(tell'in)调用1,然后使用其返回值的第一个坐标(n)作为字符串通过将其附加到其他字符串。所以无论这种类型是什么,它必须同时是一个字符串和一个数字。该错误告诉您,字符串([Char])无法被视为一种数字,当它试图解释数字文字1的含义时会出现这种情况。你可能意味着

"The list has " ++ show n ++ " elements: " ++ ...

答案 2 :(得分:1)

有一个通用的方案来理解编译错误,如果它是某种类型不匹配: 您需要提供更具体的类型注释以缩小错误!

tell'intell已有类型:

tell :: (Show a) => [a] -> String  
tell'in :: (Show a, Num n) => [a] -> n -> String -> (n, String)

所以,你改变了这个:

tell (x:xs) = "The list has " ++ n ++ " elements: " ++ s
    where (n, s) = tell'in (xs) (1) (show x)) 

对此:

--   vvvvvvvvvvvvvvvvvvvvvvv                      vvvvvvvv
tell ((x:xs)::(Show a=>[a])) = "The list has " ++ (n::Int) ++ " elements: " ++ s
    where (n::Int, s::String) = tell'in (xs) (1::Int) (show x)) 
--        ^^^^^^^^^^^^^^^^^^^^               ^^^^^^^^

现在,您已经看到错误,或者您尝试再次编译并有更具体的错误消息。


无论如何,最好使用::Int代替::Num n=>n,因为只要未指定确切类型,后者就会推广到::IntegerInt不大于一个机器字(32/64位),因此它比任意大小的Integer更快。