0

パラメータ化されたデータ型を受け取り、同じ型を返す非常に単純な関数があります。

{-# LANGUAGE ScopedTypeVariables #-}

class IntegerAsType a where
  value :: a -> Integer

newtype (Num a, IntegerAsType n) => PolyRing a n = PolyRing [a] deriving (Eq) 

normalize :: (Num a, IntegerAsType n) => (PolyRing a n) -> (PolyRing a n)
normalize r@(PolyRing xs) | (genericLength xs) == len = r
                          | ... [other cases]
           where len = (value (undefined :: n))

ノーマライズは、任意のサイズのリストを持つPolyRingを取得し、長さnのパディング/変更された係数ベクトルを持つ新しいPolyRingを返すという考え方です。ここで、nは渡されたPolyRingのタイプの一部です。

エラーが発生しました:

Ambiguous type variable `a0' in the constraint: 
(IntegerAsType a0) arising from a use of `value'

このエラーに関する他のすべてのSO投稿を確認しましたが、まだ何もありません。'len'へのすべての参照を削除しても(ただし、where句に保持して)エラーが発生するため、問題は次のようになります。

(value (undefined :: n))

これは、他の場所でIntegerAsTypeを使用した方法と実質的に同じです。

あなたがそれをしている間、私はまた、私が現在使用しているパラメータ化された型システムの代替案についての提案をしています。特に、多くの異なる値に対してIntegerAsTypeを定義する必要があるため、これは面倒です。たとえば、異なる多項式環の2つの要素を追加できないようにするために、パラメーターではなく型を使用しています(パラメーター「a」は、同じ多項式を異なる基になる環に多項式環を追加できないようにします)。

ありがとう

4

1 に答える 1

1

のシグニチャは、の型変数のnormalizeスコープを作成しません。nundefined :: n

これを試して:

normalize r@(PolyRing xs :: PolyRing a n) | ... = ...
          where len = value (undefined :: n)

forallまたは、次の型アノテーションで明示的に使用することもできますnormalize

normalize :: forall a n . (Num a, IntegerAsType n) => (PolyRing a n) -> (PolyRing a n)
normalize r@(PolyRing xs) | ... = ...
      where len = value (undefined :: n)

http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/other-type-extensions.html#decl-type-sigsを参照してください

于 2011-09-03T16:04:34.280 に答える