3

这个周末我一直在尝试学习 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>
4

3 回答 3

3

tell'in正在返回 a Num n => n,然后您在最后一个等式中(++)使用 a String(aka ) 进行. 您可能想使用而不是那里。[Char]tellshow nn

于 2011-06-06T06:20:11.693 回答
2

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

"The list has " ++ show n ++ " elements: " ++ ...
于 2011-06-06T06:24:32.670 回答
1

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

tell'in并且tell已经有类型:

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,因为后者将泛化为::Integer,只要没有指定确切的类型。Int不大于一个机器字(32/64 位),因此它比任意大小的Integer.

于 2011-06-07T01:59:07.120 回答