3

「Real World Haskell」の演習を行っています。1 つは、 の安全なバージョンを設計することですinit :: [a] -> [a]

私はから始めることになっていますsafeInit :: [a] -> Maybe [a]

これは私が現時点で持っているものです。

safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit [a] = if length [a] <= 1
    then Nothing
    else Just (take (length [a] -1) [a])

GCHi で、テストsafeInit [1,2]時にエラー メッセージが表示される

*例外: ch4exercise.hs:(21,1)-(24,44): 関数 safeInit の非網羅的なパターン

[a]のリスト (任意のサイズ) を単に表すという印象を受けましたa。私は何を間違っていますか?

4

4 に答える 4

14

型として、 「任意のサイズのs の[a]リスト」を表します。aただし、パターンとして、[a]は「要素を 1 つだけ含むリストであり、今後はその名前で知られる」ことを表しaます。同様[a,b]に、「2 つの要素を含むリスト。最初の要素は として知られa、2 番目の要素は として知られているb」などを意味します。[]、すでにご存知のように、「正確に0個の要素を含むリスト」を表します。

これは、リスト リテラルを式として記述する方法に似ています。つまり、 と書くmyList = []myListは空のリストになり、 と書くmyList = [x]myListは、変数の値である要素を 1 つだけ含むリストになりますx

于 2013-07-31T16:04:04.313 に答える
4

[] は空のリストで、何も含まれていないリストです。[a] はちょうど 1 つの要素を含むリストであり、その要素 (リストではない) は関数内で "a" として識別されます。したがって、リストに複数の要素が含まれる場合を考慮する必要があります。

"[a]" ではなく "a" だけを使用すると、"a" はリスト全体を参照し、必要な関数を使用して分解を開始できます。

空のリストがある状況については既に対処したので、if ステートメントで再度チェックする必要はないことに注意してください。

于 2013-07-31T16:05:13.753 に答える
3

Haskell で慣れなければならないことの 1 つは、かなり経験を積むまではあまり直感的ではありませんが、型レベルのものの「名前空間」が値レベルのものの名前空間と完全に分離されていることです。これは、型について話しているときと、値について話しているときでは、同じソース テキストがまったく異なる意味を持つ可能性があることを意味します。

safeInit :: [a] -> Maybe [a]

に続くもの::はすべて型について話しています。型 variable に適用される[a]リスト型コンストラクターaを次に示します。1つまり、要素が type である (任意のサイズの) リストの型ですa

safeInit [a] = if length [a] <= 1
    ...

OTOHこの方程式はレベルにあります。[a]これは type ではなく、値です(の左側は適用された値に一致するパターンで、右側は単なる値です)。値レベルでは、角括弧構文はリスト型コンストラクターではなく、リストのすべての要素が角括弧内のコンマで区切られた、リストを書くための糖衣構文です。1 つの要素を含むリストの値も同様で、変数 で示されます。リストを空にしたい場合は、 と書きます。リストに just を含めたい場合は、などと書きます。=safeInit[a]a[]ab[a, b]

値レベルでは、 (このコードの特定の評価中に)が のような 1 つの特定の値であるため[a]、 が任意の数の のリストであることはあまり意味がありません。任意の数のs のリストの式はどのような用途に使用されますか?aa3.43.4


1型コンストラクターが型変数に適用されるMaybe aのと同じです。リスト型コンストラクターの唯一の特別な点は、通常の名前ではなく呼び出され、通常のプレフィックス形式ではなく、アプリケーションのこの奇妙な「周囲の」構文を取得することです。Maybea[]

于 2013-08-01T00:18:35.580 に答える
0

この行には問題があります:

safeInit [a] = if length [a] <= 1

式の左側では、要素が 1 つだけ[a]のリストに一致します。したがって、コンパイラは、空のリストのバージョン、1 つの要素を持つリストのバージョン、しかしそれ以上の要素を持つリストのバージョンがないことを認識します。それが について不平を言っている理由です。safeInitsafeInitNon-exhaustive patterns

あなたが本当に求めているのは

safeInit a = if length a <= 1
    then Nothing
    else Just (take (length a -1) a)

要約すると:

  • 型シグネチャで[a]は、 は任意の型の要素のリストを表しaます。

  • パターンでは、[a]要素が 1 つだけあるリストに一致します。

于 2013-07-31T16:05:00.347 に答える