У меня есть довольно простая функция, которая принимает параметризованный тип данных и возвращает тот же тип:
{-# 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' гарантирует, что вы не можете добавлять кольца многочленов, модифицирующих один и тот же многочлен, но поверх разных нижележащих колец).
Спасибо