我一直在尝试使用Chinese Remainder Theorem包来实现Data.Modular,仅针对两个方程式的具体情况。我的想法是,我可以使用数字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
构造函数来使这项工作变得非常优雅和笨拙。)
答案 0 :(得分:2)
进行此编译的便宜,俗气的方法是添加FlexibleContexts
,然后将KnownNat (k1 * k2)
添加到crt
的上下文中。一旦我这样做,我就可以在ghci中成功调用它:
> crt (3 :: Mod Integer 5) (5 :: Mod Integer 7)
33
尽情享受如何将Coprime k1 k2
表达为约束......; - )