instance Monad ZipList where
    ZipList [] >>= _ = ZipList []
    ZipList (x:xs) >>= f = ZipList $ do
        let ZipList y' = f x
        guard (not (null y'))
        let ZipList ys = ZipList xs >>= ZipList . join . maybeToList . fmap snd . uncons . getZipList . f
        head y' : ys

instance MonadFail ZipList where
    fail _ = empty

instance MonadPlus ZipList