Я пытался реализовать китайскую теорему об остатках для конкретном случае всего двух уравнений с использованием данных . Модульный пакет. Идея состоит в том, что я могу указать каждое уравнение только с одним модульным числом (x = a (mod m)
, используя число a (mod m)
). Вот моя реализация.
{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeOperators #-}
import GHC.TypeLits
import Data.Proxy (Proxy (..))
import Data.Modular
crt :: forall k1 k2 i. (KnownNat k1, KnownNat k2, Integral i) => i `Mod` k1 -> i `Mod` k2 -> i `Mod` (k1 * k2)
crt a1 a2 = toMod $ (unMod a1)*n2*(unMod n2') + (unMod a2)*n1*(unMod n1')
where n1 = getModulus a1 :: i
n2 = getModulus a2 :: i
n2' = inv $ (toMod n2 :: i `Mod` k1)
n1' = inv $ (toMod n1 :: i `Mod` k2)
getModulus :: forall n i j. (Integral i, Integral j, KnownNat n) => i `Mod` n -> j
getModulus x = fromInteger $ natVal (Proxy :: Proxy n)
Я получаю следующую ошибку: Could not deduce (KnownNat (k1 * k2)) arising from a use of ‘toMod’
. Однако разве GHC не должен выполнять арифметические действия для KnownNat (k1 * k2)
? Кроме того, по какой-то странной причине, похоже, если бы у меня был конструктор для типа Mod
вместо функции toMod
, все бы работало. Я тоже не понимаю, как это должно иметь значение...
Я ищу любое исправление, чтобы помочь скомпилировать, включая любые расширения. Однако я хотел бы не создавать свою собственную версию Data.Modular, если это возможно. (Я думаю, что я мог бы сделать эту работу неэлегантной и неуклюжей, используя конструктор Mod
напрямую).
Nat
в значительной степени такие же тупые (потому что такие же общие), как и любые другие типы. Я думаю, что только 7.12 сможет сделать все это именно так, как вам хотелось бы. (Но я думаю, что есть какой-то плагин, который работает даже в 7.8.) - person leftaroundabout   schedule 03.06.2015Nat
s, за исключением этого особого случая. - person Alec   schedule 03.06.2015