content: {-# LANGUAGE StaticPointers #-}
  
  module Control.Comonad.Static where
  
  import Control.Distributed.Closure
  import Data.Functor.Static
  import Data.Typeable (Typeable)
  
  -- | Instances of 'StaticExtend' should satisfy the following laws:
  --
  -- @
  -- 'staticExtend' f = 'staticMap' f . 'staticDuplicate'
  -- 'staticDuplicate' = 'staticExtend' (static 'id')
  -- 'staticExtend' f . 'staticExtend' g = 'staticExtend' (static (.) `cap` f `cap` 'staticExtend' g)
  -- 'staticDuplicate' . 'staticDuplicate' = 'staticMap' (static 'staticDuplicate') . 'staticDuplicate'
  -- @
  class StaticFunctor w => StaticExtend w where
    staticDuplicate :: Typeable a => w a -> w (w a)
    staticDuplicate = staticExtend (static id)
  
    staticExtend :: (Typeable a, Typeable b) => Closure (w a -> b) -> w a -> w b
    staticExtend sf = staticMap sf . staticDuplicate
  
    {-# MINIMAL staticDuplicate | staticExtend #-}
  
  class StaticExtend w => StaticComonad w where
    staticExtract :: Typeable a => w a -> a
  
  instance StaticExtend Closure where
    staticDuplicate = cduplicate
  
  instance StaticComonad Closure where
    staticExtract = unclosure
  