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

这个想法是 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”确保您不能添加多项式环模相同的多项式但在不同的基础环)。

谢谢

4

1 回答 1

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

于 2011-09-03T16:04:34.280 回答