module Data.Group.Combinators
( module Data.Group
, replicate
, prop_replicate_right_distributive
) where
import Prelude hiding (replicate)
import Data.Group
import Test.QuickCheck
replicate :: (Group m, Integral n) => m -> n -> m
replicate x0 y0
| y0 < 0 = f (gnegate x0) (negate y0)
| y0 == 0 = mempty
| otherwise = f x0 y0
where
f x y
| even y = f (x `mappend` x) (y `quot` 2)
| y == 1 = x
| otherwise = g (x `mappend` x) ((y 1) `quot` 2) x
g x y z
| even y = g (x `mappend` x) (y `quot` 2) z
| y == 1 = x `mappend` z
| otherwise = g (x `mappend` x) ((y 1) `quot` 2) (x `mappend` z)
prop_replicate_right_distributive :: (Eq g, Group g, Arbitrary g, Integral n) => g -> n -> n -> Bool
prop_replicate_right_distributive g x y
= replicate g (x + y) == replicate g x `mappend` replicate g y