----------------------------------------------------------- -- | -- Module : Control.Imperative.Operators -- Copyright : (C) 2015, Yu Fukuzawa -- License : BSD3 -- Maintainer : minpou.primer@email.com -- Stability : experimental -- Portability : portable -- ----------------------------------------------------------- {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} module Control.Imperative.Operators ( -- * Operators liftOp , liftOp2 , (~$), (~*) -- *** Binary Operation , (/.), (%.), (^.), (&&.), (||.) , (==.), (/=.), (>=.), (<=.), (>.), (<.), notR, (&.), (|.), xorR, complR, (<<.), (>>.) -- *** Assignment Operators , assignModify , (=:), (+=:), (-=:), (*=:), (/=:), (%=:), (^=:), (//=:), (**=:), (<>=:) , (&&=:), (||=:), (&=:), (|=:), (<<=:), (>>=:) , (<~), (<&~) ) where import Control.Imperative.Internal import Control.Monad.Base import Data.Bits import Data.Monoid -- | Alias for 'liftOp'. (~$) :: Monad m => (a -> b) -> Ref m a -> Ref m b (~$) = liftOp {-# INLINE (~$) #-} -- | Analogous to (\<*\>) for Applicative. (~*) :: Monad m => Ref m (a -> b) -> Ref m a -> Ref m b (~*) = liftOp2 ($) {-# INLINE (~*) #-} infixl 4 ~$, ~* (/.), (%.) :: Monad m => Integral a => Ref m a -> Ref m a -> Ref m a (/.) = liftOp2 div {-# INLINE (/.) #-} (%.) = liftOp2 mod {-# INLINE (%.) #-} infixl 7 /., %. (^.) :: (Num a, Integral b, Monad m) => Ref m a -> Ref m b -> Ref m a (^.) = liftOp2 (^) {-# INLINE (^.) #-} infixr 8 ^. (&&.), (||.) :: Monad m => Ref m Bool -> Ref m Bool -> Ref m Bool (&&.) = liftOp2 (&&) {-# INLINE (&&.) #-} (||.) = liftOp2 (||) {-# INLINE (||.) #-} infixr 3 &&. infixr 2 ||. (==.), (/=.), (>=.), (<=.), (<.), (>.) :: (Ord a, Monad m) => Ref m a -> Ref m a -> Ref m Bool (==.) = liftOp2 (==) {-# INLINE (==.) #-} (/=.) = liftOp2 (/=) {-# INLINE (/=.) #-} (>=.) = liftOp2 (>=) {-# INLINE (>=.) #-} (<=.) = liftOp2 (<=) {-# INLINE (<=.) #-} (>.) = liftOp2 (>) {-# INLINE (>.) #-} (<.) = liftOp2 (<) {-# INLINE (<.) #-} infixl 4 ==., /=., >=., <=., <., >. notR :: Monad m => Ref m Bool -> Ref m Bool notR = liftOp not {-# INLINE notR #-} (&.), (|.), xorR :: (Bits a, Monad m) => Ref m a -> Ref m a -> Ref m a (&.) = liftOp2 (.&.) {-# INLINE (&.) #-} (|.) = liftOp2 (.|.) {-# INLINE (|.) #-} xorR = liftOp2 xor {-# INLINE xorR #-} infixl 7 &. infixl 5 |. (<<.), (>>.) :: (Bits a, Monad m) => Ref m a -> Ref m Int -> Ref m a (<<.) = liftOp2 shiftL {-# INLINE (<<.) #-} (>>.) = liftOp2 shiftR {-# INLINE (>>.) #-} infixl 5 <<., >>. complR :: (Bits a, Monad m) => Ref m a -> Ref m a complR = liftOp complement {-# INLINE complR #-} -- | Modify the value of mutable 'Ref' with another 'Ref'. assignModify :: MonadBase (BaseEff m) m => (a -> b -> a) -> Ref (BaseEff m) a -> Ref (BaseEff m) b -> m () assignModify f v w = ref (liftOp2 f v w) >>= assign v {-# INLINE assignModify #-} -- | An assignment operator. (=:) :: MonadBase (BaseEff m) m => Ref (BaseEff m) a -> Ref (BaseEff m) a -> m () (=:) v w = ref w >>= assign v {-# INLINE (=:) #-} (+=:), (-=:), (*=:) :: (Num a, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) a -> m () (+=:) = assignModify (+) {-# INLINE (+=:) #-} (-=:) = assignModify (-) {-# INLINE (-=:) #-} (*=:) = assignModify (*) {-# INLINE (*=:) #-} (/=:), (%=:) :: (Integral a, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) a -> m () (/=:) = assignModify div {-# INLINE (/=:) #-} (%=:) = assignModify mod {-# INLINE (%=:) #-} (^=:) :: (Num a, Integral b, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) b -> m () (^=:) = assignModify (^) {-# INLINE (^=:) #-} (//=:) :: (Fractional a, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) a -> m () (//=:) = assignModify (/) {-# INLINE (//=:) #-} (**=:) :: (Floating a, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) a -> m () (**=:) = assignModify (**) {-# INLINE (**=:) #-} (&=:), (|=:) :: (Bits a, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) a -> m () (&=:) = assignModify (.&.) {-# INLINE (&=:) #-} (|=:) = assignModify (.|.) {-# INLINE (|=:) #-} (<<=:), (>>=:) :: (Bits a, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) Int -> m () (<<=:) = assignModify shiftL {-# INLINE (<<=:) #-} (>>=:) = assignModify shiftR {-# INLINE (>>=:) #-} (<>=:) :: (Monoid a, MonadBase (BaseEff m) m) => Ref (BaseEff m) a -> Ref (BaseEff m) a -> m () (<>=:) = assignModify (<>) {-# INLINE (<>=:) #-} (&&=:), (||=:) :: MonadBase (BaseEff m) m => Ref (BaseEff m) Bool -> Ref (BaseEff m) Bool -> m () (&&=:) = assignModify (&&) {-# INLINE (&&=:) #-} (||=:) = assignModify (||) {-# INLINE (||=:) #-} -- | Run a monadic action, and assign the result of it to the mutable 'Ref'. (<~) :: MonadBase (BaseEff m) m => Ref (BaseEff m) a -> m a -> m () v <~ m = m >>= assign v {-# INLINE (<~) #-} -- | Modify the mutable 'Ref' with an endomorphism. (<&~) :: MonadBase (BaseEff m) m => Ref (BaseEff m) a -> (a -> a) -> m () v <&~ f = ref v >>= assign v . f {-# INLINE (<&~) #-} infix 2 =:, +=:, -=:, *=:, %=:, /=:, ^=:, //=:, **=: infix 2 &&=:, ||=:, &=:, |=:, <<=:, >>=:, <>=: infixr 2 <~ infix 2 <&~