2

リストの末尾を取得するために、この小さな関数を作成しました。

let getTail l = if length l > 0 then tail l else "empty list"

に渡す[]getTail戻りますempty listが、渡す[1,2,3]と次のエラーが発生します。

<interactive>:1:14:
No instance for (Num Char)
  arising from the literal `3'
Possible fix: add an instance declaration for (Num Char)
In the expression: 3
In the first argument of `getTail', namely `[1, 2, 3]'
In the expression: getTail [1, 2, 3]

そのエラーの意味がわかりません。何が問題ですか?GHCi7.0.4を使用する

4

3 に答える 3

7

関数の型について考えてみましょうgetTail。最初は、任意のリストを想像できlます。ただし、戻り値の型は a でStringある必要があります"empty list"。これは if ステートメントの一部で、 を返す可能性があるため、 である必要があるtail lことを意味l ますString

したがって、getTail関数には type がありString -> Stringます。

で呼び出すgetTail[1,2,3]、 が期待されますがString、これは単なる[Char]. 数値リテラルはオーバーロードされていることに注意してください:[1,2,3]を呼び出すのと同じ[fromInteger 1, fromInteger 2, fromInteger 3]です。したがって、このリストが与えられると、Haskell は から数値を取得しようとしますCharChars はクラスの一部ではないためNum、これは失敗し、エラーが発生します。

良い解決策は、 を返すのではなく、Maybe型を返し、エラーに対して与えることです。したがって、関数を次のように書き換えます。Nothing"empty list"

let getTail l = if length l > 0 then Just (tail l) else Nothing

現在、そのタイプは[a] -> Maybe [a]です。getTailこれを使用すると、結果を使用できるようになる前に、関数を使用するすべての人が成功したかどうかを確認する必要があります。

[]別のオプションは、「空のリスト」の代わりに戻ることです。この場合、getTail関数は とまったく同じように機能しますdrop 1

于 2012-07-21T19:19:34.743 に答える
2
Prelude> let getTail l = if length l > 0 then tail l else "empty list"

getTailあなたは型署名を与えなかったので、1つが推測されます。

Prelude> :t getTail
getTail :: [Char] -> [Char]

:tGHCiのあらゆるタイプを提供します。これは非常に便利です。型アノテーションはHaskellの関数について多くを語っています。

これはおそらくあなたが意図したことではありません。なぜそれは[Char]、(または同等にString)でのみ機能し、どのリストでも機能しないのですか?

理由は次のとおりです。

関数は1つの戻り型のみを持つことができます。"empty list"リストが空のときに戻るので、戻りタイプは。でなければなりませんStringtail xswhere xsis aの戻り型[Char]もaStringであることがたまたまあります。そのため、最初に関数を定義したときにエラーは発生しません。したがって、関数はそのままである必要があります[Char] -> [Char]

[1, 2, 3]型が。の引数を使用して呼び出しようとしていますNum a => a。GHCは、「ACharにはNumのインスタンスがありません」、または「数値をCharに変換できません」と言っています。これには型クラスが含まれます。型クラスをまだ理解していない場合でも、試したときにエラーが発生するため、問題ではありませんgetTail ([1, 2, 3] :: [Int])Intsのリストを受け取る関数にsのリストを渡そうとしていますChar

Haskell型システムを理解するためにLYAHを読むことをお勧めします。

于 2012-07-21T19:15:59.983 に答える
1

代わり[]"empty list"(タイプを混合しています)

Prelude> let getTail l = if length l > 0 then tail l else []
Prelude> getTail [1, 2, 3]
[2,3]
于 2012-07-21T19:18:19.797 に答える