1. ホーム
  2. haskell

[解決済み】なぜパースエラーになるのか?インデント?

2022-02-16 05:51:10

質問

こんなコードを書きました。

addNums key num = add [] key num
    where add res a:as b:bs
        | a == [] = res
        | otherwise = add res:(a+b) as bs

3行目でインタプリタはこう言っています。

パースエラー (インデントが正しくない可能性があります)

コードにもインデントにも間違いは見つかりませんでした。各タブには4つのスペースを入れました。

アノテーションです。

これでもコンパイルできません。

addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs

2行目

パターン内のパースエラー:追加

解決方法は?

Haskellの主なインデントルールは、定義を別の行に続ける場合は、定義しているものよりもさらにインデントしなければならない、というものです。この場合、あなたの add 関数は 以下 インデントされているので、コンパイラが文句を言っているのです。

あなたのコードの他のエラーを無視すると、インデントは次のようになるはずです。

addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs

また、正確なインデント量は問題ではなく、定義されるものに対する継続行のインデント量だけが重要であることに注意してください。

あなたのコードのもうひとつの構文的な問題は、Haskellの優先順位のルールを誤解しているようなことです。Haskellでは、関数の適用が どの演算子よりもきつく ということで add res a:as b:bs は次のようにパースされます。 (add res a):(as b):bs という意味ですが add res (a:as) (b:bs) .

最後の問題は、型エラーです。その (:) 演算子の型は a -> [a] -> [a] ということは 要素 リスト を生成します。 リスト . あなたのコードでは res:(a+b) というように、逆になっているように見えます。 res はリストであり a+b は要素です。Haskellには1つの要素を追加する演算子がないので 終了 を使う必要があります。 (++) :: [a] -> [a] -> [a] の代わりに res ++ [a+b] .

また、比較するのは 要素 a から リスト [] をガードに入れる。これはおそらく意図したものではありませんし、パターンの (a:as) はリストが空だとマッチしません。これに対する最も簡単な解決策は、ガードの代わりに別のパターンを追加することです。

これらのことをまとめると、このコードはうまくいけばあなたの意図したとおりになるはずです。

addNums key num = add [] key num
    where add res [] _ = res
          add res (a:as) (b:bs) = add (res ++ [a+b]) as bs

追伸:リストの末尾に繰り返し追加するのはあまり効率的ではありません。実際、これはO(n 2 ). 代わりに前に追加して、終わったらリストを反転させるとよいでしょう。これはO(n)です。


参考文献