При выполнении вычислений по модулю n с большими числами вы столкнетесь с огромными потерями производительности, например, при выполнении mod (123456789 ^ 987654321) n
. Вместо этого вы должны использовать свой собственный ^
, который внутренне вычисляет mod n также для промежуточных вычислений.
Конечно, я могу легко реализовать свои собственные функции, но тогда я должен явно говорить «mod n» для каждой операции. Вместо этого можно было построить дерево числовых выражений и отложить фактические вычисления, причем в конечном состоянии по модулю n только один раз. (см. мой код ниже)
Я начал с этого, чтобы четко показать, что я имею в виду, но мне интересно, существуют ли уже реализации этого, это кажется весьма полезным, поэтому кто-то должен был это реализовать.
module Modulo where
data Expr =
V Integer
| Plus Expr Expr
| Mult Expr Expr
deriving (Eq, Show)
instance Num Expr where
(+) = Plus
(*) = Mult
fromInteger = V
eval :: Integer -> Expr -> Integer
eval m (V i) = i `mod` m
eval m (Plus e1 e2) = (eval m e1 + eval m e2) `mod` m
eval m (Mult e1 e2) = (eval m e1 * eval m e2) `mod` m
fifteen :: Expr
fifteen = 10 + 5
test = eval 13 fifteen