For loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{-# LANGUAGE BangPatterns #-}
module Main ( main ) where

import Data.IORef

-- | An emulation of a C for loop.
--
--   for (first clause; second clause; third clause) { loop body }
for :: Monad m
    => a -- ^ First clause.
    -> (a -> Bool) -- ^ Second clause.
    -> (a -> a) -- ^ Third clause.
    -> (a -> m b) -- Loop body. Return value ignored for convenience.
    -> m ()
for start cond inc body = go start
    where
        go !n | cond n    = body n >> go (inc n)
              | otherwise = return ()
{-# INLINE for #-}

main = do x <- newIORef 0

          for 0 (<1000000) (+1) $
            \i -> modifyIORef x (+i)

          print =<< readIORef x

For loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- 17.5% productivity, and stack overflows.
{-# LANGUAGE BangPatterns #-}
module Main ( main ) where

import Data.IORef

-- | An emulation of a C for loop.
--
--   for (first clause; second clause; third clause) { loop body }
for :: Monad m
    => a -- ^ First clause.
    -> (a -> Bool) -- ^ Second clause.
    -> (a -> a) -- ^ Third clause.
    -> (a -> m b) -- Loop body. Return value ignored for convenience.
    -> m ()
for start cond inc body = go start
    where
        go !n | cond n    = body n >> go (inc n)
              | otherwise = return ()
{-# INLINE for #-}

main = do x <- newIORef 0

          for 0 (<1000000) (+1) $
            \i -> modifyIORef x (+i)

          print =<< readIORef x