使用hammar's help我创建了一个模块Haskell位编译
$(zModP 5)
到
newtype Z5 = Z5 Int
instance Additive.C Z5 where
(Z5 x) + (Z5 y) = Z5 $ (x + y) `mod` 5
...
我现在面临一个问题,我不认为我可以这样解决。
关于多项式的一个值得注意的事实是,如果它们是一些素数p
的不可约的模数,它们在理性中是不可约的。我已经有了一种暴力试图在给定(有限)场上对多项式进行分解的方法。
我想尝试为多个字段运行此函数。这就是我想要的东西:
isIrreducible :: (FiniteField.C a) => Poly.T a -> Bool
isIrreducible p = ...
intPolyIrreducible :: Poly.T Int -> Bool
intPolyIrreducible p = isIrreducible (p :: Poly.T Z2) ||
isIrreducible (p :: Poly.T Z3) ||
isIrreducible (p :: Poly.T Z5) ||
...
基本上我想尝试运行我的因子算法来获得大量的“除法”定义。
我认为这可能与TH有关,但似乎需要永远。我想知道将{arithmetical操作作为参数传递给isIrreducible
是否更容易?
或者看起来这可能是Newtype模块可以提供帮助的东西,但我想不出如果没有以一种同样困难的方式使用TH它会如何工作......
任何人都对如何最好地实现这一点有任何想法?
答案 0 :(得分:3)
您可以使用类型级数字在有限域中进行计算,例如使用type-level
包:
{-# LANGUAGE ScopedTypeVariables #-}
module Mod where
import Data.TypeLevel.Num (Nat,toNum, reifyIntegral)
data Z p = Z Integer
instance Eq (Z p) where Z x == Z y = x == y
instance Ord (Z p) where -- dummy instance
instance Show (Z p) where show (Z n) = show n
instance Nat p => Num (Z p) where
Z x + Z y = Z $ (x + y) `mod` toNum (undefined :: p)
Z x - Z y = Z $ (x - y) `mod` toNum (undefined :: p)
Z x * Z y = Z $ (x * y) `mod` toNum (undefined :: p)
fromInteger n = Z (n `mod` toNum (undefined :: p))
-- etc
-- Compute x^2-6 (mod p)
poly :: Nat p => Z p -> Z p
poly x = x*x-6
-- Computes whether x^2-6==0 (mod p), for x=3
checkPoly :: Integer -> Bool
checkPoly n = reifyIntegral n test
where
test :: forall p . Nat p => p -> Bool
test _ = poly (3::Z p) == 0
test1 = map checkPoly [2,3,5]
-- Result: [False,True,False]
这种方法的优点是不需要为每种数字类型使用新的模板haskell实例。缺点是它可能比模板haskell解决方案慢,因为每个操作都通过类字典传递有限字段的大小。
答案 1 :(得分:2)
这有点像Poly.T的样子,但你能编写一个类型的函数(例如)
fmap :: (a -> b) -> (Poly.T a -> Poly.T b)
?如果是这样,那么当Z
类型的模数不匹配时,其操作在运行时失败可能是有意义的:
data Z = Z Int Int
instance Applicative.C Z where
(Z m v) + (Z m' v')
| m == m' = Z m ((v + v') `mod` m)
| otherwise = error "mismatched modulus"
然后你可以用普通的旧Haskell写这样的东西:
intPolyIrreducible :: Poly.T Int -> Bool
intPolyIrreducible p = any isIrreducible [fmap (Z m) p | m <- [2,3,5,7,11,13]]
当然,这种类型安全性稍差。但从参数化的角度来看,fmap (Z m)
不会引入任何不匹配的模数。