{-# LANGUAGE MultiParamTypeClasses, NoImplicitPrelude #-}

module Control.Monad.Var.Class
  ( VarMonad (..)
  ) where

import Control.Monad (Monad)
import Data.Function ((.))
import System.IO (IO)

-- IORef
import Data.IORef (IORef, newIORef, readIORef, writeIORef)

-- MVar
import Control.Concurrent.MVar (MVar, newMVar, takeMVar, putMVar)

-- ST
import Control.Monad.ST (ST)
import Data.STRef (STRef, newSTRef, readSTRef, writeSTRef)

-- STM
import Control.Concurrent.STM (STM, atomically)
import Control.Concurrent.STM.TVar (TVar, newTVar, readTVar, writeTVar)
import Control.Concurrent.STM.TMVar (TMVar, newTMVar, takeTMVar, putTMVar)

class Monad m => VarMonad m v
  where
    new :: a -> m (v a)
    get :: v a -> m a
    put :: v a -> a -> m ()

instance VarMonad (ST s) (STRef s)
  where
    new :: forall a. a -> ST s (STRef s a)
new = a -> ST s (STRef s a)
forall a s. a -> ST s (STRef s a)
newSTRef
    get :: forall a. STRef s a -> ST s a
get = STRef s a -> ST s a
forall s a. STRef s a -> ST s a
readSTRef
    put :: forall a. STRef s a -> a -> ST s ()
put = STRef s a -> a -> ST s ()
forall s a. STRef s a -> a -> ST s ()
writeSTRef

instance VarMonad IO IORef
  where
    new :: forall a. a -> IO (IORef a)
new = a -> IO (IORef a)
forall a. a -> IO (IORef a)
newIORef
    get :: forall a. IORef a -> IO a
get = IORef a -> IO a
forall a. IORef a -> IO a
readIORef
    put :: forall a. IORef a -> a -> IO ()
put = IORef a -> a -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef

instance VarMonad IO MVar
  where
    new :: forall a. a -> IO (MVar a)
new = a -> IO (MVar a)
forall a. a -> IO (MVar a)
newMVar
    get :: forall a. MVar a -> IO a
get = MVar a -> IO a
forall a. MVar a -> IO a
takeMVar
    put :: forall a. MVar a -> a -> IO ()
put = MVar a -> a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar

instance VarMonad STM TVar
  where
    new :: forall a. a -> STM (TVar a)
new = a -> STM (TVar a)
forall a. a -> STM (TVar a)
newTVar
    get :: forall a. TVar a -> STM a
get = TVar a -> STM a
forall a. TVar a -> STM a
readTVar
    put :: forall a. TVar a -> a -> STM ()
put = TVar a -> a -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar

instance VarMonad STM TMVar
  where
    new :: forall a. a -> STM (TMVar a)
new = a -> STM (TMVar a)
forall a. a -> STM (TMVar a)
newTMVar
    get :: forall a. TMVar a -> STM a
get = TMVar a -> STM a
forall a. TMVar a -> STM a
takeTMVar
    put :: forall a. TMVar a -> a -> STM ()
put = TMVar a -> a -> STM ()
forall a. TMVar a -> a -> STM ()
putTMVar