我有一个非常简单的函数,它采用参数化数据类型并返回相同的类型:
{-# 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'确保您不能添加多项式环修改相同的多项式但在不同的底层环上)。
由于
答案 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