sessiontypes-0.1.0: src/Control/SessionTypes/Types.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilyDependencies #-}
-- | This module provides a collection of types and type families.
--
-- Specifically it defines the session type data type, capability data type and type families that compute using session types or capabilities as arguments.
module Control.SessionTypes.Types (
-- * Session Types
ST(..),
Cap(..),
GetST,
GetCtx,
-- * Duality
Dual,
DualST,
MapDual,
-- * Removing
RemoveSend,
RemoveSendST,
MapRemoveSend,
RemoveRecv,
RemoveRecvST,
MapRemoveRecv,
-- * Applying Constraints
HasConstraint,
HasConstraintST,
MapHasConstraint,
HasConstraints,
-- * Boolean functions
IfThenElse,
Not,
Or,
-- * Product type
Prod (..),
Left,
Right,
-- * Other
Nat(..),
Ref(..),
TypeEqList,
Append
) where
import Data.Kind
import Data.Typeable
infixr 6 :?>
infixr 6 :!>
-- | The session type data type
--
-- Each constructor denotes a specific session type. Using the `DataKinds` pragma the constructors are promoted to types and `ST` is promoted to a kind.
data ST a = (:?>) a (ST a) -- ^ Send a value
| (:!>) a (ST a) -- ^ Recv a value
| Sel [ST a] -- ^ Selection of branches
| Off [ST a] -- ^ Offering of branches
| R (ST a) -- ^ Delimit the scope of recursion
| Wk (ST a) -- ^ Weaken the scope of recursion
| V -- ^ Recursion variable
| Eps -- ^ End of the session
deriving Typeable
-- | A capability that stores a context/scope that is a list of session types and a session type
data Cap a = Cap [ST a] (ST a) deriving Typeable
-- | Retrieves the session type from the capability
type family GetST s where
GetST ('Cap ctx s) = s
-- | Retrieves the context from the capability
type family GetCtx s where
GetCtx ('Cap ctx s) = ctx
-- | Type family for calculating the dual of a session type. It may be applied to a capability.
--
-- We made `Dual` injective to support calculating the dual of a selection that contains
-- an ambiguous branch. Of course that does require that the dual of that ambiguous branch must be known.
type family Dual s = r | r -> s where
Dual ('Cap ctx s) = 'Cap (MapDual ctx) (DualST s)
-- | Type family for calculating the dual of a session type. It may be applied to the actual session type.
type family DualST (a :: ST c) = (b :: ST c) | b -> a where
DualST (s :!> r) = s :?> DualST r
DualST (s :?> r) = s :!> DualST r
DualST (Sel xs) = Off (MapDual xs)
DualST (Off xs) = Sel (MapDual xs)
DualST (R s) = R (DualST s)
DualST (Wk s) = Wk (DualST s)
DualST V = V
DualST Eps = Eps
-- | Type family for calculating the dual of a list of session types.
type family MapDual xs = ys | ys -> xs where
MapDual '[] = '[]
MapDual (s ': xs) = DualST s ': MapDual xs
-- | Type family for removing the send session type from the given session type. It may be applied to a capability.
type family RemoveSend s where
RemoveSend ('Cap ctx s) = 'Cap (MapRemoveSend ctx) (RemoveSendST s)
-- | Type family for removing the send session type from the given session type. It may be applied to a session type.
type family RemoveSendST s where
RemoveSendST (a :!> r) = RemoveSendST r
RemoveSendST (a :?> r) = a :?> RemoveSendST r
RemoveSendST (Sel xs) = Sel (MapRemoveSend xs)
RemoveSendST (Off xs) = Off (MapRemoveSend xs)
RemoveSendST (R s) = R (RemoveSendST s)
RemoveSendST (Wk s) = Wk (RemoveSendST s)
RemoveSendST s = s
-- | Type family for removing the send session type from a list of session types.
type family MapRemoveSend ctx where
MapRemoveSend '[] = '[]
MapRemoveSend (s ': ctx) = RemoveSendST s ': MapRemoveSend ctx
-- | Type family for removing the receive session type from the given session type. It may be applied to a capability.
type family RemoveRecv s where
RemoveRecv ('Cap ctx s) = 'Cap (MapRemoveRecv ctx) (RemoveRecvST s)
-- | Type family for removing the receive session type from the given session type. It may be applied to a session type.
type family MapRemoveRecv ctx where
MapRemoveRecv '[] = '[]
MapRemoveRecv (s ': ctx) = RemoveRecvST s ': MapRemoveRecv ctx
-- | Type family for removing the receive session type from a list of session types.
type family RemoveRecvST s where
RemoveRecvST (a :!> r) = a :!> RemoveRecvST r
RemoveRecvST (a :?> r) = RemoveRecvST r
RemoveRecvST (Sel xs) = Sel (MapRemoveRecv xs)
RemoveRecvST (Off xs) = Off (MapRemoveRecv xs)
RemoveRecvST (R s) = R (RemoveRecvST s)
RemoveRecvST (Wk s) = Wk (RemoveRecvST s)
RemoveRecvST s = s
-- | Type family for applying a constraint to types of kind `Type` in a session type. It may be applied to a capability.
type family HasConstraint (c :: Type -> Constraint) s :: Constraint where
HasConstraint c ('Cap ctx s) = (HasConstraintST c s, MapHasConstraint c ctx)
-- | Type family for applying a constraint to types of kind `Type` in a session type. It may be applied to a session type.
type family MapHasConstraint (c :: Type -> Constraint) ss :: Constraint where
MapHasConstraint c '[] = ()
MapHasConstraint c (s ': ss) = (HasConstraintST c s, MapHasConstraint c ss)
-- | Type family for applying a constraint to types of kind `Type` in a list of session types.
type family HasConstraintST (c :: Type -> Constraint) s :: Constraint where
HasConstraintST c (a :!> r) = (c a, HasConstraintST c r)
HasConstraintST c (a :?> r) = (c a, HasConstraintST c r)
HasConstraintST c (Sel '[]) = ()
HasConstraintST c (Sel (s ': xs)) = (HasConstraintST c s, HasConstraintST c (Sel xs))
HasConstraintST c (Off '[]) = ()
HasConstraintST c (Off (s ': xs)) = (HasConstraintST c s, HasConstraintST c (Off xs))
HasConstraintST c (R s) = HasConstraintST c s
HasConstraintST c (Wk s) = HasConstraintST c s
HasConstraintST c V = ()
HasConstraintST c s = ()
-- | Type family for applying zero or more constraints to types of kind `Type` in a list of session types. It may be applied to a capability.
type family HasConstraints (cs :: [Type -> Constraint]) s :: Constraint where
HasConstraints '[] s = ()
HasConstraints (c ': cs) s = (HasConstraint c s, HasConstraints cs s)
-- | Type family for applying zero or more constraints to types of kind `Type` in a list of session types. It may be applied to a session type.
type family HasConstraintsST (cs :: [Type -> Constraint]) s :: Constraint where
HasConstraintsST '[] s = ()
HasConstraintsST (c ': cs) s = (HasConstraintST c s, HasConstraintsST cs s)
-- | Type family for applying zero or more constraints to types of kind `Type` in a list of session types. It may be applied to a list of session types.
type family MapHasConstraints (cs :: [Type -> Constraint]) ctx :: Constraint where
MapHasConstraints '[] ctx = ()
MapHasConstraints (c ': cs) ctx = (MapHasConstraint c ctx, MapHasConstraints cs ctx)
-- | Promoted `ifThenElse`
type family IfThenElse (b :: Bool) (l :: k) (r :: k) :: k where
IfThenElse 'True l r = l
IfThenElse 'False l r = r
-- | Promoted `not`
type family Not b :: Bool where
Not 'True = 'False
Not 'False = 'True
-- | Promoted `||`
type family Or b1 b2 :: Bool where
Or 'True b = 'True
Or b 'True = 'True
Or b1 b2 = 'False
-- | Data type that takes a kind as an argument. Its sole constructor takes two capabilities parameterized by the kind argument.
--
-- This data type is useful if it is necessary for an indexed monad to be indexed by four parameters.
data Prod t = (:*:) (Cap t) (Cap t)
-- | Type family for returning the first argument of a product.
type family Left p where
Left (l :*: r) = l
-- | Type family for returning the second argument of a product.
type family Right p where
Right (l :*: r) = r
-- | Data type defining natural numbers
data Nat = Z | S Nat deriving (Show, Eq, Ord)
-- | Data type that can give us proof of membership of an element in a list of elements.
data Ref s xs where
RefZ :: Ref s (s ': xs)
RefS :: Ref s (k ': xs) -> Ref s (t ': k ': xs)
-- | Type family for computing which types in a list of types are equal to a given type.
type family TypeEqList xs s where
TypeEqList '[s] s = '[True]
TypeEqList '[r] s = '[False]
TypeEqList (s ': xs) s = 'True ': TypeEqList xs s
TypeEqList (r ': xs) s = 'False ': TypeEqList xs s
-- | Promoted `++`
type family Append xs ys where
Append '[] ys = ys
Append (x ': xs) ys = x ': xs `Append` ys