{-# LANGUAGE CPP, NoImplicitPrelude, UnicodeSyntax #-}

module Utils
    ( mask
    , mask_
    , (!)
    , void
    , ifM
    , purelyModifyMVar
    , modifyIORefM
    , modifyIORefM_
    ) where

--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------

-- from base:
import Control.Concurrent.MVar ( MVar, takeMVar, putMVar )
import Control.Monad           ( Monad, return, (>>=) )
import Data.Bool               ( Bool )
import Data.Function           ( ($) )
import Data.IORef              ( IORef, readIORef, writeIORef )
import Prelude                 ( ($!) )
import System.IO               ( IO )

#if __GLASGOW_HASKELL__ < 700
import Control.Monad           ( (>>), fail )
#endif

-- from base-unicode-symbols:
import Data.Function.Unicode   ( () )


--------------------------------------------------------------------------------
-- Utility functions
--------------------------------------------------------------------------------

#if MIN_VERSION_base(4,3,0)
import Control.Exception       ( mask, mask_ )
import Control.Monad           ( void )
#else
import Control.Exception       ( blocked, block, unblock )
import Data.Function           ( id )
import Data.Functor            ( Functor, (<$) )

mask  ((IO α  IO α)  IO β)  IO β
mask io = blocked >>= \b  if b then io id else block $ io unblock

mask_  IO α  IO α
mask_ = block

void  Functor f  f α  f ()
void = (() <$)
#endif

-- | Strict function composition.
(!)  (β  γ)  (α  β)  (α  γ)
f ! g = (f $!)  g

ifM  Monad m  m Bool  m α  m α  m α
ifM c t e = c >>= \b  if b then t else e

purelyModifyMVar  MVar α  (α  α)  IO ()
purelyModifyMVar mv f = mask_ $ takeMVar mv >>= putMVar mv ! f

modifyIORefM  IORef α  (α  IO (α, β))  IO β
modifyIORefM r f = do (y, z)  readIORef r >>= f
                      writeIORef r y
                      return z

modifyIORefM_  IORef α  (α  IO α)  IO ()
modifyIORefM_ r f = readIORef r >>= f >>= writeIORef r


-- The End ---------------------------------------------------------------------