{-# LANGUAGE AllowAmbiguousTypes, TypeApplications #-} -- | Testing the code in the introduction of the paper. module Intro where import Control.Monad import System.Environment (getArgs) import Test.QuickCheck import Control.Monad.Credit data Batched a = Batched [a] [a] deriving (Eq, Ord, Show) rev :: MonadCount m => [a] -> [a] -> m [a] rev [] acc = pure acc rev (x : xs) acc = tick >> rev xs (x : acc) batched :: MonadCount m => [a] -> [a] -> m (Batched a) batched [] rear = do front <- rev rear [] pure $ Batched front [] batched front rear = pure $ Batched front rear empty :: MonadCount m => m (Batched a) empty = pure $ Batched [] [] snoc :: MonadCount m => Batched a -> a -> m (Batched a) snoc (Batched front rear) x = batched front (x : rear) uncons :: MonadCount m => Batched a -> m (Maybe (a, Batched a)) uncons (Batched [] []) = pure Nothing uncons (Batched (x:front) rear) = do q' <- batched front rear pure $ Just (x, q') unfoldM :: Monad m => (b -> m (Maybe (a, b))) -> b -> m [a] unfoldM f b = do mb <- f b case mb of Nothing -> pure [] Just (x, b') -> (x :) <$> unfoldM f b' testBatched :: Either String ([Int], Ticks) testBatched = runCounterM $ empty >>= flip (foldM snoc) [1..10] >>= unfoldM uncons