Неоднозначный тип с использованием параметризованных типов Haskell - PullRequest
0 голосов
/ 03 сентября 2011

У меня есть довольно простая функция, которая принимает параметризованный тип данных и возвращает тот же тип:

{-# 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 со списком любого размера, а затем вернет новыйPolyRing с вектором коэффициента дополнения / изменения длины n, где 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 Ответ

1 голос
/ 03 сентября 2011

Подпись для 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

...