Небольшое изменение go
и f
решило проблему:
instance KnownNat n => Semigroup (Symmetric n) where
x <> y = go x [] n where
n = toInteger (natVal (Proxy :: Proxy n))
go :: forall m. Symmetric m -> [(Integer,Integer)] -> Integer -> Symmetric m
go S1 _ _ = S1
go (_ :. xs) j m = let
i = sIndex x (sIndex y (n-m))
ix = foldr f i j
in Cyclic ix :. go xs ((ix,m) :j) (m-1)
f (j,m) i = let
ix = (i - j) `mod` m - 1
in if 0 <= ix then ix else ix + m
Основная идея - ввести фиктивный параметр.Также обратите внимание, что Cyclic
был использован вместо cyclic
.
К сожалению, оказывается, что я неправильно сделал некоторые математические вычисления.Это должно быть исправлено.
РЕДАКТИРОВАТЬ: Вот исправленное sIndex
, которое завершает экземпляр:
sIndex :: forall n. KnownNat n => Symmetric n -> Integer -> Integer
sIndex xs m = let
n = toInteger (natVal (Proxy :: Proxy n))
in sIndex_ xs (m `mod` n) n
where
sIndex_ :: Symmetric m -> Integer -> Integer -> Integer
sIndex_ S1 _ _ = 0
sIndex_ (x :. _) 0 _ = cIndex x
sIndex_ (x :. xs) m n = let
i = cIndex x + sIndex_ xs (m-1) (n-1) + 1
in if n <= i then i - n else i
Я также заметил, что x
иy
поменялись местами в определении <>
, которое затем исправляется выше.