1

次のように機能するレプリケートのような関数を書きたい:

repli "the" 3 = "ttthhheee" and repli "jason" 4 = "jjjjaaaasssssoooonnnn"

ここに私が書いたコードがあります:

myrepli []  n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))


repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n)

私が得るエラーはこれです:

Couldn't match expected type `[a]' against inferred type `Char'
     Expected type: [[a]]
     Inferred type: [Char]
   In the first argument of `repli', namely `"jason"'
   In the expression: repli "jason" 3

どうすればこれを修正できますか? ありがとう。

4

2 に答える 2

8

型の問題については、これが私を大いに助けてくれたトリックです。このようなメッセージに完全に困惑するたびに、私は次のことを行います。

  • 問題の関数に型シグネチャがある場合は、それを削除して、何かが変わるかどうかを確認します。コンパイルできたら、ghci にタイプを尋ねます ( を使用:t)。コンパイルされない場合、少なくともエラー メッセージが異なるため、別の手がかりが得られる可能性があります。
  • 型シグネチャがない場合は、1 つ追加します。コンパイルされない場合でも、エラー メッセージから別の手がかりが得られる場合があります。
  • それでも問題が解決しない場合は、関数内の各式に型宣言を一時的に追加します。ScopedTypeVariables(多くの場合、実際に何が起こっているかを確認するために、いくつかの式を分割する必要があります。プラグマを一時的に有効にする必要がある場合もあります。) 再度コンパイルして、エラー メッセージを確認します。

最後の 1 つはより多くの作業ですが、私はその演習から多くのことを学びました。それは通常、私が考えている型と GHC が考えている型との間に不一致がある正確な場所を特定します。

それでは、コードに型シグネチャを追加することから始めましょう。

myrepli :: [a] -> Int -> [a]
myrepli []  n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))


repli :: [a] -> Int -> [a]
repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n) -- triggers a compiler error

ああ、今度はコンパイラ エラーが発生します。

amy.hs:9:27:
    Couldn't match expected type `a' with actual type `[a]'
      `a' is a rigid type variable bound by
          the type signature for repli :: [a] -> Int -> [a] at amy.hs:7:10
    In the first argument of `myrepli', namely `x'
    In the first argument of `(++)', namely `(myrepli x n)'
    In the expression: (myrepli x n) ++ (repli xs n)

問題は への呼び出しにありmyrepli x nます。関数myrepliはリスト/文字列を想定していますが、1 つの文字を渡しています。その最後の行を次のように変更します。

repli (x:xs) n = (myrepli [x] n) ++ (repli xs n)

その時点で、コード内に他のエラーが見つかります。ただし、コードを修正するのではなく、別の方法を紹介しましょう。

repl (x:xs) n = (myReplicate x n) ++ (repl xs n)
repl [] _ = []

-- You could use the library function "replicate" here, but as a
-- learning exercise, we'll write our own.
myReplicate a n = take n (repeat a)
于 2014-02-18T12:20:35.620 に答える