Я думаю, что проблема в том, что GH C не знает, что (1 + d) не равно 0 для любого d.
Чтобы определить перекрытие, вы смотрите только на право =>
. Они перекрываются:
SumVectorSized 0
SumVectorSized d'
Как мне понять, что экземпляры не перекрываются?
Добавить {-# OVERLAPPING #-}
ко второму экземпляру.
Или есть ли другой способ сделать этот тип индукции?
Это один из многих приемов, чтобы смягчить отсутствие зависимых типов в Haskell. Разумное решение - обратиться к зависимо типизированному языку, такому как Idris или Agda, где индукцию можно сформулировать как простую функцию.
Менее радикальной альтернативой является go через одноэлементный тип Peano:
data NatS (n :: Nat) where
ZS :: NatS 0
SS :: (n' ~ (n-1), n ~ (1 + n')) => NatS n' -> NatS n
Техника, которую вы описали, требует нового класса типов для каждой операции, которую вы хотите выполнить, требуя дублирования этого неприглядного трюка с перекрывающимися экземплярами. Вам нужен только один из этих классов для преобразования ограничения KnownNat
в одноэлементное значение NatS
, а затем все остальное - простая функция:
sumVS :: NatS n -> V.Vector n Int -> Int
sumVS ZS _ = 0
sumVS (SS n) v = V.head v + sumVS (V.tail v)