简体   繁体   English

使用KnownNat算法让GHC接受类型签名

[英]Getting the GHC to accept type signature with KnownNat arithmetic

I have been trying to implement the Chinese Remainder Theorem , for the specific case of just two equations, using the Data.Modular package. 我一直在尝试使用Data.Modular包来实现中国剩余定理 ,仅针对两个方程的具体情况。 The idea is that I can specify each equation with only one modular number ( x = a (mod m) using the number a (mod m) ). 我的想法是,我可以使用数字a (mod m)指定每个方程只有一个模数( x = a (mod m) a (mod m) )。 Here is my implementation. 这是我的实施。

{-# 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)

I get the following error: Could not deduce (KnownNat (k1 * k2)) arising from a use of 'toMod' . 我收到以下错误: Could not deduce (KnownNat (k1 * k2)) arising from a use of 'toMod' However, shouldn't GHC be able to do the arithmetic for KnownNat (k1 * k2) ? 但是,GHC不能为KnownNat (k1 * k2)做算术吗? Also, for some weird reason, it looks like if I had a constructor for the Mod type instead of the toMod function, everything would work. 此外,由于一些奇怪的原因,看起来如果我有一个Mod类型的toMod函数而不是toMod函数,一切都会工作。 I fail to see how that should make a difference either... 我不明白这应该如何有所作为......

I am looking for any fix to help this compile, including whatever extensions. 我正在寻找任何修复来帮助编译,包括任何扩展。 I would, however, like to not have to make my own version of Data.Modular if possible. 但是,如果可能的话,我希望不必制作我自己的Data.Modular版本。 (I think I could make this work inelegantly and clumsily by using the Mod constructor directly). (我想我可以通过直接使用Mod构造函数来使这项工作变得非常优雅和笨拙)。

The cheap, cheesy way to make this compile is to add FlexibleContexts , then add KnownNat (k1 * k2) to the context of crt . 进行编译的廉价,俗气的方法是添加FlexibleContexts ,然后将KnownNat (k1 * k2)crt的上下文中。 Once I did this, I could successfully call it in ghci: 一旦我这样做,我可以成功地在ghci中调用它:

> crt (3 :: Mod Integer 5) (5 :: Mod Integer 7)
33

Have fun working out how to express Coprime k1 k2 as a constraint... ;-) 玩得开心如何表达Coprime k1 k2作为约束...... ;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM