{- | Module  : Control.Monad.Graph Description : Graph indexed monads Copyright  : (c) Aaron Friel License  : BSD-3 Maintainer  : Aaron Friel Stability  : unstable Portability : portable -} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} -- For the default Apply, Then, and But instances. {-# LANGUAGE UndecidableInstances #-} module Control.Monad.Graph where import Control.Graphted.Class import Control.Applicative.Graph -- | Graph indexed monad. class GApplicative m => GMonad (m :: p -> * -> *) where -- | The apply operation ('>>=') on the graph index. -- -- Default instance: @Bind m i j = 'Combine' m i j@ type family Bind m (i :: p) (j :: p) :: p type instance Bind m i j = Combine m i j -- | An invariant on the indexes of 'Bind'. -- -- Default instance: @BindInv m i j = 'Inv' m i j@ type family BindInv m (i :: p) (j :: p) :: Constraint type instance BindInv m i j = Inv m i j -- | The join operation ('Control.Monad.join') on the graph index. -- -- Default instance: @Join m i j = 'Bind' m i j@ type family Join m (i :: p) (j :: p) :: p type instance Join m i j = Bind m i j -- | An invariant on the indexes of 'Join'. -- -- Default instance: @JoinInv m i j = 'BindInv' m i j@ type family JoinInv m (i :: p) (j :: p) :: Constraint type instance JoinInv m i j = BindInv m i j -- | Sequentially compose two actions, with the second dependent on the first. gbind :: BindInv m i j => m i a -> (a -> m j b) -> m (Bind m i j) b -- | Remove one level of nested structure. -- -- Default implementation requires the default instance of 'Join'. {-# INLINE gjoin #-} gjoin :: (JoinInv m i j) => m i (m j b) -> m (Join m i j) b default gjoin :: (Bind m i j ~ Join m i j, BindInv m i j) => m i (m j b) -> m (Join m i j) b gjoin x = x `gbind` id