1

私は Haskell のプロではありません。今日、私は型システムに関してやや奇妙な経験をしました。この 2 行目は型エラーを引き起こします。問題はmaxdiag (as:bs:cs:ds)2 行目のビットです。

maxdiag ((a:as):(b:bs):(c:cs):(d:ds):xs) len =
  maximum [a*(bs !! 0)*(cs !! 1)*(ds !! 2), maxdiag (as:bs:cs:ds) (len-1)]

次のエラーで失敗します。

Occurs check: cannot construct the infinite type: a0 = [a0]
Expected type: [[a0]]
  Actual type: [a0]
In the second argument of `(:)', namely `ds'
In the second argument of `(:)', namely `cs : ds'

2 行目の問題のある部分を に変更すると、次のmaxdiag (as:bs:cs:ds:xs)ようになります。

maxdiag ((a:as):(b:bs):(c:cs):(d:ds):xs) len =
  maximum [a*(bs !! 0)*(cs !! 1)*(ds !! 2), maxdiag (as:bs:cs:ds:xs) (len-1)]

...それならエラーはありません。同様に、それを置き換えるとmaxdiag (as:bs:cs:(ds:xs))成功します。私の質問は

  1. このエラーはどういう意味ですか?
  2. なぜそれが起こったのですか?
  3. これら 2 つの一見異なることが問題を解決するのはなぜですか?
4

2 に答える 2

9

覚えておくべきこと(:)は、タイプa -> [a] -> [a]が であるため、最初の引数は要素であり、2 番目の引数はその要素タイプのリストです。要素自体がリストの場合、これは になり[a] -> [[a]] -> [[a]]ます。

あなたの例ではas、 、bscsおよびdsall は type[a]xs持っていますが、 type を持っている[[a]]ので、適切に型付けされているcs:ds間はエラーになります。ds:xs

その特定のエラー メッセージの理由は(:)、同じタイプの 2 つのものに対して を使用しようとすると、 が と同じタイプでbある場合にのみ動作しますが、それは許可されていない無限タイプになるためです。b[b]

もう 1 つの質問では、(:)演算子は右結合なので、 and とas:bs:cs:ds:xs同じです。as:(bs:(cs:(ds:xs)))as:bs:cs:(ds:xs)

于 2012-05-06T18:32:06.503 に答える
5

エラー:

A.hs:2:63:
    Occurs check: cannot construct the infinite type: a0 = [a0]
    Expected type: [[a0]]
      Actual type: [a0]
    In the second argument of `(:)', namely `ds'
    In the second argument of `(:)', namely `cs : ds'

型に再帰的な制約があることを意味しますが、これは違法です。つまり、タイプaは と の両方aである必要があり[a]ます。

発生チェック」は、この時点で実行されている型チェック アルゴリズムの一部の技術名です。「発生チェック」は、無限再帰型の構築を防ぎます。

(:)私の経験では、リストのようなエラーで発生チェックに失敗するということは、とを混同していることを意味します(++)。つまり、値をリスト要素として使用することもあれば、リスト自体として使用することもあります。

この場合、それは(:)式中の の使用ですas:bs:cs:ds。おそらくあなたは次のようなことを意味します:

[as,bs,cs,ds]++xs

コードは非常に複雑であることに注意してください。リスト内の要素の数と形状について、常に真である可能性はほとんどありません。私はこのコードがとても怖いです。次のようにする方がはるかに安全です。

  • パターン マッチングを使用して、他のケース (空のリスト、要素の欠落など) を除外します。
  • インデックス (!!) をパターン マッチングに置き換えます。

アルゴリズムを単純化する方法をよく考えてください。

于 2012-05-06T18:34:33.610 に答える