使用参数化类型Haskell的不明确类型

时间:2011-09-03 15:56:19

标签: haskell parameterized ambiguous gadt

我有一个非常简单的函数,它采用参数化数据类型并返回相同的类型:

{-# 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))

我们的想法是,normalize将使用任何大小的列表进行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。我们使用类型而不是参数来确保,例如,您不能添加不同多项式环的两个元素(参数'a'确保您不能添加多项式环修改相同的多项式但在不同的底层环上)。

由于

1 个答案:

答案 0 :(得分:1)

normalize的签名不会为n中的类型变量undefined :: 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