3

I've been doing my annual attempt to learn Haskell this weekend, and as ever when I actually try to write a recursive function (rather than just type one in from a tutorial), I get a type error.

I'd very much appreciate any help understanding (1) what the error means (I don't understand the "fix"); and (2) why an error is being thrown at all - I'm fairly certain I'm not making any mistakes regarding the types being passed.

My code:

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)

And the error I get when I try to load this into 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 is returning a Num n => n, which you are then (++)ing with a String (aka [Char]) in the last equation for tell. You probably want to use show n instead of n there.

于 2011-06-06T06:20:11.693 に答える
2

の型はtell'in、戻り値の最初の座標が 2 番目の引数と同じ型になることを示しています。では、数値を 2 番目の引数 ( ) としてtell呼び出し、その戻り値 ( ) の最初の座標を他の文字列に追加して文字列として使用しています。したがって、この型が何であれ、同時に文字列と数値である必要があります。このエラーは、文字列 ( ) を一種の数値と見なす方法がないことを示しています。これは、数値リテラル の意味を解釈しようとしたときに発生します。あなたはおそらく意味したtell'in1n[Char]1

"The list has " ++ show n ++ " elements: " ++ ...
于 2011-06-06T06:24:32.670 に答える
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代わりに使用することをお勧めします。は1 マシン ワード (32/64 ビット) よりも大きくないため、任意サイズの よりも高速です。::Num n=>n::IntegerIntInteger

于 2011-06-07T01:59:07.120 に答える