Почему Хаскелл интерпретирует мой тип NUM как перечисление?
-
20-09-2019 - |
Вопрос
Я пытаюсь собрать следующую функцию в Хаскелле, чтобы имитировать дифференциацию полинома, чьи константы указаны в числовом списке:
diff :: (Num a) => [a] -> [a]
diff [] = error "Polynomial unspecified"
diff coeff = zipWith (*) (tail coeff) [0..]
Haskell отказывается скомпилировать его, давая мне следующую причину:
Could not deduce (Enum a) from the context (Num a)
arising from the arithmetic sequence `0 .. ' at fp1.hs:7:38-42
Possible fix:
add (Enum a) to the context of the type signature for `diff'
In the third argument of `zipWith', namely `[0 .. ]'
In the expression: zipWith (*) (tail coeff) ([0 .. ])
In the definition of `diff':
diff coeff = zipWith (*) (tail coeff) ([0 .. ])
Почему Haskell относится к [0..]
Список как тип перечисления, и как я могу это исправить. Имейте в виду, что я хочу воспользоваться ленивой оценкой здесь, отсюда и бесконечный список.
Решение
[0..]
это синтаксический сахар для enumFrom 0
, определено в классе Enum
. Анкет Потому что вы хотите собрать список a
с [0..]
Компилятор требует a
быть в классе Enum
.
Вы можете добавить Enum a
на тип подписи функции или обойти ее, генерируя [0..] :: [Integer]
и использование fromInteger
(что определено в классе Num
) чтобы получить [a]
От этого:
diff :: (Num a) => [a] -> [a]
diff [] = error "Polynomial unspecified"
diff coeff = zipWith (*) (tail coeff) (map fromInteger [0..])
Другие советы
Правильный тип diff
должен быть
diff :: (Num a, Enum a) => [a] -> [a]
Потому что использование [x..]
Требуется тип экземпляра Enum
.
[0..]
это сокращение enumFrom 0
Глянь сюда
Вот краткое изложение того, что компилятор видит, когда он смотрит на эту функцию:
- 0 ..] - это список вещей, которые имеют экземпляры NUM и Enum. Это должно быть число из -за «0», и это должно быть перечисление из -за «..»
- Меня просят подать заявку (*) к элементам коэффициента и [0 ..] один за другим. Поскольку оба аргумента (*) должны быть одинаковым типом, а [0 ..] имеет экземпляр для Enum, коэффициент также должен иметь экземпляр для Enum.
- Ошибка! Тип сигнатура только Diff упоминает, что у коэффициента есть экземпляр для NUM, но я уже определил, что он должен, по крайней мере, иметь экземпляр для Enum.