packages feed

loop 0.2.0 → 0.3.0

raw patch · 5 files changed

+61/−7 lines, 5 filesdep +foldlsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: foldl

API changes (from Hackage documentation)

+ Control.Loop: forLoopState :: Monad m => a -> (a -> Bool) -> (a -> a) -> b -> (b -> a -> m b) -> m b
+ Control.Loop: numLoopState :: (Num a, Eq a, Monad m) => a -> a -> b -> (b -> a -> m b) -> m b
- Control.Loop: numLoop :: (Num a, Eq a, Monad m) => a -> a -> (a -> m ()) -> m ()
+ Control.Loop: numLoop :: (Num a, Ord a, Monad m) => a -> a -> (a -> m ()) -> m ()

Files

− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
bench/Bench.hs view
@@ -2,6 +2,7 @@  module Main (main) where +import qualified Control.Foldl as Foldl import           Control.Monad import           Criterion.Main import qualified Data.Vector as V@@ -41,6 +42,7 @@                    , bench "uvectorEnumFromToInt"         $ nfIO $ uvectorEnumFromToInt         0 (1000000 :: Int)    (\_ -> return ())                 -- Allocates the vector -> linear space and slow                 -- , bench "uvectorEnumFromNInt"          $ nfIO $ uvectorEnumFromNInt          0 (1000000 :: Int)    (\_ -> return ())+                   , bench "FoldL.FoldM"                  $ nfIO $ Foldl.foldM (Foldl.FoldM (\_m _x -> return ()) (return ()) return) [1..1000000::Int]                    ]      , bgroup "w32" [ bench "loop"                          $ nfIO $ loop                        0 (1000000 :: Word32) (\_ -> return ())@@ -57,6 +59,7 @@                    , bench "vectorEnumFromToW32"           $ nfIO $ vectorEnumFromToW32         0 (1000000 :: Word32) (\_ -> return ())                    , bench "uvectorFromListW32"            $ nfIO $ uvectorFromListW32          0 (1000000 :: Word32) (\_ -> return ())                    , bench "uvectorEnumFromToW32"          $ nfIO $ uvectorEnumFromToW32        0 (1000000 :: Word32) (\_ -> return ())+                   , bench "FoldL.FoldM"                   $ nfIO $ Foldl.foldM (Foldl.FoldM (\_m _x -> return ()) (return ()) return) [1..1000000::Word32]                    ]      -- `succ` is almost twice as slow as (+1) because it does an overflow check.
loop.cabal view
@@ -1,5 +1,5 @@ name:          loop-version:       0.2.0+version:       0.3.0 license:       MIT copyright:     2014 Niklas Hambüchen <mail@nh2.me> author:        Niklas Hambüchen <mail@nh2.me>@@ -17,7 +17,7 @@   `forM_ [1..n]` idiom, which in many cases GHC cannot fuse to efficient   code.   .-  See https://ghc.haskell.org/trac/ghc/ticket/8763.+  See <https://ghc.haskell.org/trac/ghc/ticket/8763>.  source-repository head   type:      git@@ -64,6 +64,7 @@     , criterion           >= 0.6.0.0     , random              >= 1.0.1.1     , vector              >= 0.10.9.1+    , foldl               >= 1.0.0   ghc-options:     -Wall -O2 
src/Control/Loop.hs view
@@ -26,8 +26,10 @@ --   @forLoop 1 (<= n) (+1)@. module Control.Loop   ( forLoop+  , forLoopState   , forLoopFold   , numLoop+  , numLoopState   , numLoopFold   ) where @@ -43,6 +45,17 @@ {-# INLINE forLoop #-}  +-- | @forLoopState start cond inc initialState f@: A C-style for loop with+-- starting value, loop condition, incrementor and a state that is threaded+-- through the computation.+forLoopState :: (Monad m) => a -> (a -> Bool) -> (a -> a) -> b -> (b -> a -> m b) -> m b+forLoopState start cond inc initialState f = go start initialState+  where+    go !x !state | cond x    = f state x >>= go (inc x)+                 | otherwise = return state++{-# INLINE forLoopState #-}+ -- | @forLoopFold start cond inc acc0 f@: A pure fold using a for loop -- instead of a list for performance. --@@ -62,15 +75,29 @@ -- | @numLoop start end f@: Loops over a contiguous numerical range, including -- @end@. --+-- Does nothing when not @start <= end@.+-- -- It uses @(+ 1)@ so for most integer types it has no bounds (overflow) check.-numLoop :: (Num a, Eq a, Monad m) => a -> a -> (a -> m ()) -> m ()-numLoop start end f = go start+numLoop :: (Num a, Ord a, Monad m) => a -> a -> (a -> m ()) -> m ()+numLoop start end f = if start <= end then go start else return ()   where     go !x | x == end  = f x           | otherwise = f x >> go (x+1)  {-# INLINE numLoop #-} +-- | @numLoopState start end f initialState@: Loops over a contiguous numerical+-- range, including @end@ threading a state through the computation.+--+-- It uses @(+ 1)@ so for most integer types it has no bounds (overflow) check.+numLoopState :: (Num a, Eq a, Monad m) => a -> a -> b -> (b -> a -> m b) -> m b+numLoopState start end initState f = go start initState+  where+    go !x !state | x == end  = f state x+                 | otherwise = f state x >>= go (x+1)+++{-# INLINE numLoopState #-}  -- | @numLoopFold start end acc0 f@: A pure fold over a contiguous numerical -- range, including @end@.
test/Main.hs view
@@ -5,7 +5,7 @@ import           Data.Word import           Test.Hspec -import           Control.Loop (forLoop, numLoop, numLoopFold)+import           Control.Loop   main :: IO ()@@ -53,6 +53,18 @@       res `shouldBe` (maxBound :: Word32)  +  describe "forLoopState" $ do++    it "monadic and threaded state" $ do+      let res = flip execState 0 $ do+            _ <- forLoopState (0 :: Int) (<= 10) (+1) (1 :: Int) $ \st i -> do+                    x <- get+                    put $! x + st + i+                    return (st * 2)+            return ()++      res `shouldBe` sum (map (\a -> a + 2 ^ a) [0 .. 10])+   describe "numLoop" $ do      it "is inclusive" $ do@@ -62,6 +74,19 @@               put $! x + i        res `shouldBe` 55+++  describe "numLoopState" $ do++    it "monadic and threaded state" $ do+      let res = flip execState 0 $ do+            _ <- numLoopState (0 :: Int) 10 (1 :: Int) $ \st i -> do+                        x <- get+                        put $! x + st + i+                        return (st * 2)+            return ()++      res `shouldBe` sum (map (\a -> a + 2 ^ a) [0 .. 10])     describe "numLoopFold" $ do