I'm very new to Haskell and am trying to create a type that will represent any instance of Integral over some modulus. I found some example code online and am working with that, so my type definition looks like this:
data Zn n a = Zn !a !a
Most things are working as I'd like; I can show, add, subtract, etc.
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
However, I can't show the results of arithmetic operations on these types. For example, in 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
I've found this issue has come up in a number of other ways that I've tried to implement these numbers, and understanding how the Data.Reflection package works is giving me some troubles. I'd also be curious about any other implementations that seem more natural to others. I had originally tried doing something like
newtype Zn n a = Zn a
and switched because I thought that it would simplify things, which it hasn't in particular. Cheers!
Aucun commentaire:
Enregistrer un commentaire