我对 Haskell 很陌生,并且正在尝试创建一种类型,该类型将代表 Integral 在某个模数上的任何实例。我在网上找到了一些示例代码并正在使用它,所以我的类型定义如下所示:
data Zn n a = Zn !a !a
大多数事情都按照我的意愿进行;我可以显示、加、减等。
instance (Integral a, Show a) => Show (Zn n a) where
show (Zn n x) = printf "(%s mod %s)" (show (mod x n)) (show n)
instance (Integral a, Reifies n a) => Num (Zn n a) where
Zn n x + Zn _ y = Zn n (mod (x + y) n)
Zn n x - Zn _ y = Zn n (mod (x - y) n)
Zn n x * Zn _ y = Zn n (mod (x * y) n)
negate (Zn n x) = Zn n (n - x)
abs = id
signum x@(Zn _ 0) = x
signum (Zn n _) = Zn n 1
fromInteger x = Zn n (mod (fromInteger x) n)
where n = reflect (Proxy :: Proxy n)
znToIntegral :: Integral a => Zn n a -> a
znToIntegral (Zn n x) = fromIntegral x
但是,我无法显示这些类型的算术运算结果。例如,在 GHCi 中:
*Main> let x = Zn 5 3
*Main> x
(3 mod 5)
*Main> let y = Zn 5 7
(2 mod 5)
*Main> let z = x + y
*Main> z
<interactive>:6:1:
No instance for (Integral a0) arising from a use of ‘print’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Integral GHC.Int.Int16 -- Defined in ‘GHC.Int’
instance Integral GHC.Int.Int32 -- Defined in ‘GHC.Int’
instance Integral GHC.Int.Int64 -- Defined in ‘GHC.Int’
...plus 9 others
In a stmt of an interactive GHCi command: print it
我发现这个问题在我尝试实现这些数字的许多其他方式中出现,并且了解 Data.Reflection 包的工作方式给我带来了一些麻烦。我也会对其他人似乎更自然的任何其他实现感到好奇。我最初尝试做类似的事情
newtype Zn n a = Zn a
并切换,因为我认为它会简化事情,它并没有特别。干杯!