{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StaticPointers #-}
{-# LANGUAGE UndecidableInstances #-}
module Control.Monad.Static where
import Control.Applicative.Static
import Control.Distributed.Closure
import Data.Functor.Static
import Data.Typeable (Typeable)
-- | Instances of 'StaticBind' should satisfy the following laws (writing
-- 'staticMap', 'staticApply', 'staticBind' as infix @('<$>')@, @('<*>')@, @(>>=)@,
-- respectively):
--
-- @
-- (m >>= f) >>= g = m >>= static (.) ``cap`` (staticFlippedBind g) `cap` f
-- 'staticJoin' . 'staticJoin' = 'staticJoin' . 'staticMap' (static 'staticJoin')
-- @
--
-- where
--
-- @
-- staticFlippedBind :: Closure (b -> m c) -> Closure (m b -> m c)
-- staticFlippedBind = capDup (static (flip staticBind))
-- @
class StaticApply m => StaticBind m where
staticBind :: (Typeable a, Typeable b) => m a -> Closure (a -> m b) -> m b
staticBind m k = staticJoin (staticMap k m)
staticJoin :: Typeable a => m (m a) -> m a
staticJoin m = m `staticBind` static id
{-# MINIMAL staticBind | staticJoin #-}
class (StaticApplicative m, StaticBind m) => StaticMonad m
instance (StaticApplicative m, StaticBind m) => StaticMonad m
staticReturn :: (StaticApplicative m, Typeable a) => a -> m a
staticReturn = staticPure
instance StaticBind Closure where
staticBind m k = unclosure k (unclosure m)