import Test.QuickCheck
import Data.Maybe

myRepeat :: Int -> a -> Maybe [a]
myRepeat 0 x = Just []
myRepeat n x =
	case n < 0 of
		True -> Nothing
		otherwise -> Just $ [x] ++ (fromJust (myRepeat (n - 1) x))

myReplicate :: Int -> [a] -> Maybe [a]
myReplicate n xs =
	case n < 0 of
		True -> Nothing
		otherwise -> Just $ concatMap (\x -> fromJust (myRepeat n x)) xs

-- Define a SmallTestInt type, which we will create an Arbitrary instance for
-- to pick Integers in the range [-5, 5] for testing. Larger integers result in
-- us replicating very large lists, making the tests run very slowly.

newtype SmallTestInt = SmallTestInt Int deriving (Show, Eq, Ord)

instance Arbitrary SmallTestInt where
	arbitrary = fmap SmallTestInt (choose (-5, 5))

fromSmallTestInt :: SmallTestInt -> Int
fromSmallTestInt (SmallTestInt i) = i

-- Test the two functions we've defined.

testMyRepeat :: SmallTestInt -> Int -> Bool
testMyRepeat n x =
	case myRepeat (fromSmallTestInt n) x of
		Nothing -> n < (SmallTestInt 0)
		Just xs -> xs == replicate (fromSmallTestInt n) x

testMyReplicate :: SmallTestInt -> [Int] -> Bool
testMyReplicate n xs =
	case myReplicate (fromSmallTestInt n) xs of
		Nothing -> n < (SmallTestInt 0)
		Just ys -> (length ys == (fromSmallTestInt n) * length xs)
			&& ys == concatMap (replicate (fromSmallTestInt n)) xs

main = do
	quickCheck testMyRepeat
	quickCheck testMyReplicate
	return ()
