packages feed

monad-timing 0.1.0.0 → 0.1.0.1

raw patch · 3 files changed

+70/−32 lines, 3 filesdep +hspecdep +monad-timingdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: hspec, monad-timing

Dependency ranges changed: base

API changes (from Hackage documentation)

- Control.Monad.Timing: [_runTimingT] :: TimingT m a -> m (a, [TimingTree])
- Control.Monad.Timing: runTimingT :: MonadIO m => TimingT m a -> m (a, TimingTree)
+ Control.Monad.Timing: [runTimingT] :: TimingT m a -> m (a, [TimingTree])
+ Control.Monad.Timing: timingAll :: MonadIO m => TimingT m a -> m (a, TimingTree)
- Control.Monad.Timing: execTimingT :: MonadIO m => TimingT m b -> m TimingTree
+ Control.Monad.Timing: execTimingT :: MonadIO m => TimingT m b -> m [TimingTree]

Files

monad-timing.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                monad-timing-version:             0.1.0.0+version:             0.1.0.1 synopsis:            Monad transformer for recording timing events description:         Monad transformer for recording timing events homepage:            https://github.com/pikajude/monad-timing@@ -36,6 +36,14 @@   type:                exitcode-stdio-1.0   main-is:             hlint.hs   build-depends:       base, hlint+  hs-source-dirs:      test+  default-language:    Haskell2010+  ghc-options:         -w -threaded -rtsopts -with-rtsopts=-N++test-suite sanity+  type:                exitcode-stdio-1.0+  main-is:             sanity.hs+  build-depends:       base, containers, hspec, monad-timing, transformers   hs-source-dirs:      test   default-language:    Haskell2010   ghc-options:         -w -threaded -rtsopts -with-rtsopts=-N
src/Control/Monad/Timing.hs view
@@ -13,7 +13,7 @@       MonadTiming(..), TimingTree, Tag,        -- * @TimingT@, general timing handler-      TimingT(..), runTimingT, execTimingT,+      TimingT(..), execTimingT, timingAll,        -- * @NoTimingT@, a no-timing handler       NoTimingT (..)@@ -46,32 +46,21 @@ type Tag = String  -- | A monad transformer that records timing events.------ Note that this module exports both '_runTimingT' and 'runTimingT'.------ * '_runTimingT' returns the timing events verbatim without sanitization.--- * 'runTimingT' combines trees with the same 'Tag' and tags the duration--- of the entire computation with the special tag @\<all\>@.-newtype TimingT m a = TimingT { _runTimingT :: m (a, [TimingTree]) }+newtype TimingT m a = TimingT {+    -- | Run the giving @TimingT@ computation, recording timing events.+    runTimingT :: m (a, [TimingTree]) } +-- | Wrap an entire @TimingT@ computation in a timing event.+timingAll :: MonadIO m => TimingT m a -> m (a, TimingTree)+timingAll = fmap (second head) . runTimingT . timeGroup "<all>"+ evalTimingT :: Functor f => TimingT f b -> f b-evalTimingT = fmap fst . _runTimingT+evalTimingT = fmap fst . runTimingT  -- | Run a @TimingT@ computation, discarding the result.-execTimingT :: MonadIO m => TimingT m b -> m TimingTree+execTimingT :: MonadIO m => TimingT m b -> m [TimingTree] execTimingT = fmap snd . runTimingT --- | Run the giving @TimingT@ computation, recording timing events.-runTimingT :: MonadIO m => TimingT m a -> m (a, TimingTree)-runTimingT = fmap (second (head . condenseTree)) . _runTimingT . timeGroup "<all>"--condenseTree :: [TimingTree] -> [TimingTree]-condenseTree = map (foldl collapseNodes emptyNode)-             . groupBy ((==) `on` (fst . rootLabel)) where-    collapseNodes (Node (_, x) sub) (Node (t, x1) sub2)-        = Node (t, x + x1) (condenseTree $ sub ++ sub2)-    emptyNode = Node ("", 0) []- liftTimingT :: Functor m => m a -> TimingT m a liftTimingT = TimingT . fmap (\ x -> (x, [])) @@ -85,13 +74,19 @@  instance Alternative m => Alternative (TimingT m) where     empty = liftTimingT empty-    a <|> b = TimingT $ _runTimingT a <|> _runTimingT b+    a <|> b = TimingT $ runTimingT a <|> runTimingT b  instance Monad m => Monad (TimingT m) where     TimingT a >>= f = TimingT $ do         (thing1, b) <- a-        (thing2, c) <- _runTimingT $ f thing1-        return (thing2, b ++ c)+        (thing2, c) <- runTimingT $ f thing1+        return (thing2, condenseTree $ b ++ c)+        where+            condenseTree = map (foldl collapseNodes emptyNode)+                         . groupBy ((==) `on` (fst . rootLabel)) where+                collapseNodes (Node (_, x) sub) (Node (t, x1) sub2)+                    = Node (t, x + x1) (condenseTree $ sub ++ sub2)+                emptyNode = Node ("", 0) []  instance MonadTrans TimingT where     lift = liftTimingT@@ -102,16 +97,16 @@ instance MonadPlus m => MonadPlus (TimingT m) where  instance MonadReader r m => MonadReader r (TimingT m) where-    local f m = TimingT $ local f $ _runTimingT m+    local f m = TimingT $ local f $ runTimingT m     ask = lift ask  instance MonadWriter w m => MonadWriter w (TimingT m) where     tell = lift . tell     listen m = TimingT $ do-        ~((a, b), c) <- listen (_runTimingT m)+        ~((a, b), c) <- listen (runTimingT m)         return ((a, c), b)     pass m = TimingT $ pass $ do-        ~((a, b), c) <- _runTimingT m+        ~((a, b), c) <- runTimingT m         return ((a, c), b)  instance MonadState s m => MonadState s (TimingT m) where@@ -127,17 +122,17 @@     throwM e = TimingT $ throwM e  instance MonadCatch m => MonadCatch (TimingT m) where-    TimingT a `catch` f = TimingT $ a `catch` (_runTimingT . f)+    TimingT a `catch` f = TimingT $ a `catch` (runTimingT . f)  instance MonadMask m => MonadMask (TimingT m) where-    mask a = TimingT $ mask $ \ u -> _runTimingT (a $ q u) where+    mask a = TimingT $ mask $ \ u -> runTimingT (a $ q u) where         q u (TimingT m) = TimingT (u m)-    uninterruptibleMask a = TimingT $ uninterruptibleMask $ \ u -> _runTimingT (a $ q u) where+    uninterruptibleMask a = TimingT $ uninterruptibleMask $ \ u -> runTimingT (a $ q u) where         q u (TimingT m) = TimingT (u m)  instance MonadError e m => MonadError e (TimingT m) where     throwError = TimingT . throwError-    TimingT a `catchError` f = TimingT $ a `catchError` (_runTimingT . f)+    TimingT a `catchError` f = TimingT $ a `catchError` (runTimingT . f)  instance MonadBase b m => MonadBase b (TimingT m) where     liftBase = lift . liftBase
+ test/sanity.hs view
@@ -0,0 +1,35 @@+module Main where++import Control.Concurrent+import Control.Exception      (PatternMatchFail (..), catch)+import Control.Monad.IO.Class+import Control.Monad.Timing+import Data.Tree+import Test.Hspec++main :: IO ()+main = hspec $ do+    describe "TimingT" $ do+        it "records timing" $ do+            (_, tree) <- runTimingT $+                timeGroup "foo" $ liftIO $ threadDelay 1000+            tree `shouldMatchPattern`+                (\ [ Node ("foo", x) [] ] -> x >= 0.001)++        it "condenses multiple groups into one" $ do+            (_, tree) <- runTimingT $ do+                timeGroup "foo" $ liftIO $ threadDelay 1000+                timeGroup "foo" $ liftIO $ threadDelay 2000+            tree `shouldMatchPattern`+                (\ [ Node ("foo", x) [] ] -> x >= 0.003)++        it "preserves subgroups" $ do+            (_, tree) <- runTimingT $ do+                timeGroup "foo" $ timeGroup "bar" $ liftIO $ threadDelay 1000+                timeGroup "foo" $ timeGroup "bar" $ liftIO $ threadDelay 2000+            tree `shouldMatchPattern`+                (\ [ Node ("foo", x) [ Node ("bar", y) [] ] ] -> x >= 0.003 && y >= 0.003)++shouldMatchPattern n f = catch+    (f n `shouldBe` True)+    (\ (PatternMatchFail s) -> expectationFailure $ "pattern did not match: " ++ show n)