isPrefix :: (Eq a) => [a] -> [a] -> Bool
isPrefix xs ys = take (length xs) ys == xs
suffixes :: [a] -> [[a]]
suffixes xs = [drop n xs | n <- [0..length xs - 1]]
contains :: (Eq a) => [a] -> [a] -> Bool
contains xs ys = or [isPrefix ys xs' | xs' <- suffixes xs]
stutter :: [a] -> Int -> [a]
stutter [] _ = []
stutter (x:xs) n = replicate n x ++ stutter xs n
stutter' :: [a] -> Int -> [a]
stutter' xs n = concat [replicate n x | x <- xs]
-- stutter' xs n = concat [y | x <- xs, let y = replicate n x]
stutter'' :: [a] -> Int -> [a]
stutter'' xs n = foldr (\x -> (replicate n x ++)) [] xs
data Tree a = Leaf a | Fork (Tree a) (Tree a) deriving Show
zipTrees :: Tree a -> Tree b -> Tree (a,b)
zipTrees (Leaf v1) (Leaf v2) = Leaf (v1, v2)
zipTrees (Fork x1 y1) (Fork x2 y2) = Fork (zipTrees x1 x2) (zipTrees y1 y2)
foldTree :: (a -> b) -> (b -> b -> b) -> Tree a -> b
foldTree f _ (Leaf x) = f x
foldTree f g (Fork x y) = g (foldTree f g x) (foldTree f g y)
mapTree :: (a -> b) -> (Tree a) -> (Tree b)
mapTree f = foldTree (Leaf . f) Fork
addTrees :: (Num a) => (Tree a) -> (Tree a) -> (Tree a)
addTrees x y = mapTree (uncurry (+)) $ zipTrees x y