module SequenceCheck where

import qualified Data.Sequence as Seq
import qualified Data.List as List
import qualified Data.Foldable as Fold
import Data.List
import Data.Sequence
import Test.QuickCheck
import Data.Foldable

prop_replicate :: Int -> Int -> Property
prop_replicate n x = let repSeq = Seq.replicate n x in
	n >= 0 ==> (valid repSeq && toList repSeq == List.replicate n x)

prop_zip :: [Int] -> [Int] -> Bool
prop_zip xs ys = let xys = Seq.zip (fromList xs) (fromList ys)
	in  valid xys && List.zip xs ys == toList xys

prop_scanl :: [Int] -> Bool
prop_scanl xs = let ys = Seq.scanl f [] (fromList xs) in 
	valid ys && toList ys == List.scanl f [] xs
	where	f xs x = x:xs

prop_scanr :: [Int] -> Bool
prop_scanr xs = let ys = Seq.scanr (:) [] (fromList xs) in 
	valid ys && toList ys == List.scanr (:) [] xs

prop_tails :: [Int] -> Bool
prop_tails xs = let xss = Seq.tails (fromList xs) in
	valid xss && Fold.all valid xss && map toList (toList xss) == List.tails xs

prop_inits :: [Int] -> Bool
prop_inits xs = let xss = Seq.inits (fromList xs) in
	valid xss && Fold.all valid xss && map toList (toList xss) == List.inits xs


prop_span :: [Int] -> Bool
prop_span xs = let (ys1, ys2) = Seq.span even (fromList xs) in 
	valid ys1 && valid ys2 && (toList ys1, toList ys2) == List.span even xs

prop_unfoldr :: [Int] -> Bool
prop_unfoldr xs = let ys = Seq.unfoldr unfold xs in valid ys && toList ys == xs
	where	unfold (x:xs) = Just (x, xs)
		unfold [] = Nothing

prop_iterate :: Int -> Property
prop_iterate n = n >= 0 ==> let ys= Seq.iterate n (+1) 0 in valid ys && toList ys == List.take n (List.iterate (+1) 0)

prop_partition :: [Int] -> Bool
prop_partition xs = let (ys1, ys2) = Seq.partition even (Seq.fromList xs) in
	valid ys1 && valid ys2 && (toList ys1, toList ys2) == List.partition even xs

prop_append :: [Int] -> [Int] -> Bool
prop_append xs ys = let xys = Seq.fromList xs >< Seq.fromList ys in 
	valid xys && toList xys == xs ++ ys

main = do	quickCheck (label "replicate" prop_replicate)
		quickCheck (label "zip" prop_zip)
		quickCheck (label "scanl" prop_scanl)
		quickCheck (label "scanr" prop_scanr)
		quickCheck (label "tails" prop_tails)
		quickCheck (label "inits" prop_inits)
		quickCheck (label "span" prop_span)
		quickCheck (label "unfoldr" prop_unfoldr)
		quickCheck (label "iterate" prop_iterate)
		quickCheck (label "partition" prop_partition)
		quickCheck (label "append" prop_append)
