{-# LANGUAGE Safe #-}
module Data.Chatty.Counter where
import Control.Applicative
import Control.Arrow
import Control.Monad
import Control.Monad.Trans.Class
newtype CounterT m a = Counter { CounterT m a -> Int -> m (a, Int)
runCounterT :: Int -> m (a,Int) }
instance Functor m => Functor (CounterT m) where
fmap :: (a -> b) -> CounterT m a -> CounterT m b
fmap a -> b
f CounterT m a
a = (Int -> m (b, Int)) -> CounterT m b
forall (m :: * -> *) a. (Int -> m (a, Int)) -> CounterT m a
Counter ((Int -> m (b, Int)) -> CounterT m b)
-> (Int -> m (b, Int)) -> CounterT m b
forall a b. (a -> b) -> a -> b
$ \Int
s -> ((a, Int) -> (b, Int)) -> m (a, Int) -> m (b, Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> (a, Int) -> (b, Int)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first a -> b
f) (m (a, Int) -> m (b, Int)) -> m (a, Int) -> m (b, Int)
forall a b. (a -> b) -> a -> b
$ CounterT m a -> Int -> m (a, Int)
forall (m :: * -> *) a. CounterT m a -> Int -> m (a, Int)
runCounterT CounterT m a
a Int
s
instance (Functor m,Monad m) => Applicative (CounterT m) where
pure :: a -> CounterT m a
pure = a -> CounterT m a
forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: CounterT m (a -> b) -> CounterT m a -> CounterT m b
(<*>) = CounterT m (a -> b) -> CounterT m a -> CounterT m b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad m => Monad (CounterT m) where
return :: a -> CounterT m a
return a
a = (Int -> m (a, Int)) -> CounterT m a
forall (m :: * -> *) a. (Int -> m (a, Int)) -> CounterT m a
Counter ((Int -> m (a, Int)) -> CounterT m a)
-> (Int -> m (a, Int)) -> CounterT m a
forall a b. (a -> b) -> a -> b
$ \Int
s -> (a, Int) -> m (a, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a,Int
s)
CounterT m a
m >>= :: CounterT m a -> (a -> CounterT m b) -> CounterT m b
>>= a -> CounterT m b
f = (Int -> m (b, Int)) -> CounterT m b
forall (m :: * -> *) a. (Int -> m (a, Int)) -> CounterT m a
Counter ((Int -> m (b, Int)) -> CounterT m b)
-> (Int -> m (b, Int)) -> CounterT m b
forall a b. (a -> b) -> a -> b
$ \Int
s -> do (a
a,Int
s') <- CounterT m a -> Int -> m (a, Int)
forall (m :: * -> *) a. CounterT m a -> Int -> m (a, Int)
runCounterT CounterT m a
m Int
s; CounterT m b -> Int -> m (b, Int)
forall (m :: * -> *) a. CounterT m a -> Int -> m (a, Int)
runCounterT (a -> CounterT m b
f a
a) Int
s'
instance MonadTrans CounterT where
lift :: m a -> CounterT m a
lift m a
m = (Int -> m (a, Int)) -> CounterT m a
forall (m :: * -> *) a. (Int -> m (a, Int)) -> CounterT m a
Counter ((Int -> m (a, Int)) -> CounterT m a)
-> (Int -> m (a, Int)) -> CounterT m a
forall a b. (a -> b) -> a -> b
$ \Int
s -> do a
a <- m a
m; (a, Int) -> m (a, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a,Int
s)
class Monad m => ChCounter m where
countOn :: m Int
instance Monad m => ChCounter (CounterT m) where
countOn :: CounterT m Int
countOn = (Int -> m (Int, Int)) -> CounterT m Int
forall (m :: * -> *) a. (Int -> m (a, Int)) -> CounterT m a
Counter ((Int -> m (Int, Int)) -> CounterT m Int)
-> (Int -> m (Int, Int)) -> CounterT m Int
forall a b. (a -> b) -> a -> b
$ \Int
s -> (Int, Int) -> m (Int, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
s,Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
withCounter :: (Monad m,Functor m) => CounterT m a -> m a
withCounter :: CounterT m a -> m a
withCounter CounterT m a
m = ((a, Int) -> a) -> m (a, Int) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, Int) -> a
forall a b. (a, b) -> a
fst (m (a, Int) -> m a) -> m (a, Int) -> m a
forall a b. (a -> b) -> a -> b
$ CounterT m a -> Int -> m (a, Int)
forall (m :: * -> *) a. CounterT m a -> Int -> m (a, Int)
runCounterT CounterT m a
m Int
0