1

プログラムをData.Arrayの使用からData.Array.Unboxedに変換しようとしています。

簡単な補足として、コードで「配列」を「UArray」に変更し、Data.Array.Unboxedのインポートを追加できると記載されている場所がいくつかありますが、両方のタイプの配列を混合していないため、Data.Arrayをインポートしました。 Data.Arrayの代わりに.Unboxed、これで十分ですか?

切り替えを行うと、次の書き換えルールが破られます。

{-# RULES
    "applyWindow/applyWindow" forall win1 win2 image. 
                                     applyWindow win1 
                                                 (applyWindow win2 
                                                 image) = 
                                     applyWindow (indexMult win1 win2) 
                                                            image
  #-}

ここで、win1win2とimageはすべてUArrayである必要があります。ただし、これは次のエラーでコンパイルに失敗します。

FIPlib/Core.hs:229:99:
    Ambiguous type variables `e0', `a0' in the constraint:
      (IArray a0 e0) arising from a use of `applyWindow'
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: applyWindow (indexMult win1 win2) image
    When checking the transformation rule "applyWindow/applyWindow"

FIPlib/Core.hs:229:99:
    Ambiguous type variables `e0', `a2' in the constraint:
      (IArray a2 e0) arising from a use of `applyWindow'
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: applyWindow (indexMult win1 win2) image
    When checking the transformation rule "applyWindow/applyWindow"

FIPlib/Core.hs:229:112:
     Ambiguous type variables `e0', `a1' in the constraint:
      (IArray a1 e0) arising from a use of `indexMult'
    Probable fix: add a type signature that fixes these type variable(s)
    In the first argument of `applyWindow', namely
      `(indexMult win1 win2)'
    In the expression: applyWindow (indexMult win1 win2) image
    When checking the transformation rule "applyWindow/applyWindow"

これがあいまいな理由は何ですか?Data.Arrayで動作するときに、これが機能しないのはなぜですか?

4

2 に答える 2

3

問題は、をData.Array.Unboxed再エクスポートすることですData.Array.IArray。したがって、IArray不変配列インターフェイスのクラスは再エクスポートしますが、Data.Arrayインポートしません(インポートすらしません)。したがって、インポートされただけboundsaccumArray、などの関数を使用する場合、それらは配列型では単形であるため、あいまいさは発生しません(要素型のポリモーフィズムは、ここでは明らかに問題になりません。適切な型クラスの制約があれば問題ありません)。 。ただし、インポートすると、これらすべての関数に制約が発生するため、書き換えには異なる配列型が含まれる可能性があり、したがって破損します。関数またはintルールで、型シグネチャを使用して型を修正する必要があります。これをどのように正確に解決するかは、コードを見ずに言うことはできません。arrayData.ArrayData.Array.UnboxedIArray a e

注:型チェックは7.4、ghc-7.4.1で変更されました。インポートする場合、ルールのないコードは型シグネチャなしではコンパイルされませんData.Array.Unboxed

ルールがあいまいにならないように型を修正するには、型シグネチャを指定する必要があります

  • トップレベルで、へapplyWindow
  • との2つのローカルバインディングpaddedImagefilteredPaddedImage

おそらく望ましく、最も合理的なのは、関係するすべての配列が同じタイプを持つことです。

  1. 単形型、たとえばUArray (Int,Int) Int(要素型はWord、...)
  2. 配列型では単形型、要素型では多型型
  3. 両方のタイプのploymorphic

1.の場合、署名を追加するだけで済みますapplyWindow :: T -> T -> T(目的のタイプはxxImage :: TどこにありますかT)。2.の場合、2つの言語拡張機能を追加する必要がFlexibleContextsありScopedTypeVariables、その後applyWindow、署名を取得します

applyWindow :: forall e. (Num e, IArray UArray e)
            => UArray (Int,Int) e -> UArray (Int,Int) e -> UArray (Int,Int) e

ローカルバインディングは署名を取得しますxxImage :: UArray (Int,Int) e。は、constarintでFlexibleContextsの発生を許可するために必要であり、要素タイプをスコープに入れて、型シグネチャを取得できるようにするために必要です。3.の場合、必要なのは、の型アノテーションは次のようになります。UArrayScopedTypeVariablespaddedImagefilteredPaddedImageScopedTypeVariablesapplyWindow

applyWindow :: forall a e. (Num e, IArray a e) => ...

すべての配列を強制的に同じ型にする別の方法は、asTypeOfそれらすべてを使用するか、リストに入れることです(未使用のローカルバインディング)が、IMO型シグネチャが推奨されます。

すべての型が修正されると(必ずしも同じである必要はありませんが、ローカルバインディングの型は、引数と結果の型、場合によっては引数の型のみによって決定される必要があります)、ルールは型チェックを行う必要があります。(タイプも修正する必要があるかもしれませindexMultん。)

于 2012-02-12T17:42:52.427 に答える
2

インポートだけで、配列の明示的な型署名なしで(この場合)このコードを実行しようとすると、まったく同じエラーメッセージ(IArrayなどについて)を受け取りました。署名を追加したときは、すべて問題ありませんでした。多分これもあなたを助けるでしょう。UArray Int BoolData.Array.Unboxed

于 2012-02-12T01:22:37.410 に答える