私は 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
と切り替えました。乾杯!