sessiontypes-0.1.0: src/Control/SessionTypes/Indexed.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE FunctionalDependencies #-}
-- | This module provides a set of indexed type classes (IxFunctor, IxApplicative, IxMonad, etc..) that correspond to existing type classes (Functor, Applicative, Monad, etc..)
--
-- The intent of this module is to replace the use of non-indexed type classes with indexed type class.
--
-- For that reason the indexed type classes expose functions that are named the same as the functions exposed by a corresponding non-indexed type class.
--
-- There are two ways to use this module:
--
-- @
-- import SessionTypes
-- import qualified SessionTypes.Indexed as I
--
-- prog = send 5 I.>> eps0
-- @
--
-- @
-- {-\# LANGUAGE RebindableSyntax \#-}
-- import SessionTypes
-- import SessionTypes.Indexed
--
-- prog = do
-- send 5
-- eps0
-- @
--
-- With `RebindableSyntax` we construct a custom do notation by rebinding (>>=) with (>>=) of `IxMonad`.
-- Rebinding is not limited to only (>>=), but also all other functions in Prelude.
--
-- We do not want to force importing Prelude if you use `RebindableSyntax`.
-- Therefore this module also exports Prelude that hides functions already defined by
-- the indexed type classes.
module Control.SessionTypes.Indexed (
-- * Classes
IxFunctor(..),
IxApplicative(..),
IxMonad(..),
-- ** Transformers
IxMonadT(..),
IxMonadIxT(..),
-- ** Mtl
IxMonadReader(..),
-- ** Exception
IxMonadThrow(..),
IxMonadCatch(..),
IxMonadMask(..),
-- ** MonadIO
IxMonadIO(..),
-- * Combinators
ap,
-- * Rebind
ifThenElse,
module PH,
) where
import Control.Exception
import Data.Kind (Type)
import Prelude as PH hiding ((>>=),(>>), return, fail, fmap, pure, (<*>))
class IxFunctor (f :: p -> p -> Type -> Type) where
fmap :: (a -> b) -> f j k a -> f j k b
class IxFunctor f => IxApplicative (f :: p -> p -> Type -> Type) where
pure :: a -> f i i a
(<*>) :: f s r (a -> b) -> f r k a -> f s k b
infixl 1 >>=
infixl 1 >>
class IxApplicative m => IxMonad (m :: p -> p -> Type -> Type) where
(>>=) :: m s t a -> (a -> m t k b) -> m s k b
(>>) :: m s t a -> m t k b -> m s k b
return :: a -> m i i a
fail :: String -> m i i a
m1 >> m2 = m1 >>= \_ -> m2
fail = error
-- | Type class for lifting monadic computations
class IxMonad (t m) => IxMonadT t m where
lift :: m a -> t m s s a
-- | Type class for lifting indexed monadic computations
class IxMonad (t m) => IxMonadIxT t m where
ilift :: m s r a -> t m s r a
-- | Type class representing the indexed monad reader
class IxMonad m => IxMonadReader r m | m -> r where
ask :: m s s r
local :: (r -> r) -> m s t a -> m s t a
reader :: (r -> a) -> m i i a
-- | Type class for indexed monads in which exceptions may be thrown.
class IxMonad m => IxMonadThrow m s where
-- | Provide an `Exception` to be thrown
throwM :: Exception e => e -> m s s a
-- | Type class for indexed monads to allow catching of exceptions.
class IxMonadThrow m s => IxMonadCatch m s where
-- | Provide a handler to catch exceptions.
catch :: Exception e => m s s a -> (e -> m s s a) -> m s s a
-- | Type class for indexed monads that may mask asynchronous exceptions.
class IxMonadCatch m s => IxMonadMask m s where
-- | run an action that disables asynchronous exceptions. The provided function can be used to restore the occurrence of asynchronous exceptions.
mask :: ((m s s b -> m s s b) -> m s s b) -> m s s b
-- | Ensures that even interruptible functions may not raise asynchronous exceptions.
uninterruptibleMask :: ((m s s b -> m s s b) -> m s s b) -> m s s b
-- | Type class for indexed monads that may lift IO computations.
class IxMonadIO m where
liftIO :: IO a -> m s s a
ifThenElse :: Bool -> t -> t -> t
ifThenElse True b1 _ = b1
ifThenElse False _ b2 = b2
-- # Combinators
ap :: IxMonad m => m s r (a -> b) -> m r k a -> m s k b
ap f g = f >>= \f' -> g >>= \g' -> return (f' g')