content: {-# LANGUAGE StaticPointers #-}
  
  module Data.Profunctor.Static (StaticProfunctor(..)) where
  
  import Control.Distributed.Closure
  import Data.Typeable (Typeable)
  
  -- | Instances of 'StaticProfunctor' should satisfy the following laws:
  --
  -- @
  -- 'staticDimap' (static id) (static id) = static id
  -- 'staticLmap' (static id) = static id
  -- 'staticRmap' (static id) = static id
  -- 'staticDimap' f g = staticLmap f . staticRmap g
  -- @
  class Typeable p => StaticProfunctor p where
    staticDimap
      :: (Typeable a, Typeable b, Typeable c, Typeable d)
      => Closure (a -> b) -> Closure (c -> d) -> p b c -> p a d
    staticDimap sf sg = staticLmap sf . staticRmap sg
  
    staticLmap
      :: (Typeable a, Typeable b, Typeable c)
      => Closure (a -> b) -> p b c -> p a c
    staticLmap sf = staticDimap sf (static id)
  
    staticRmap
      :: (Typeable a, Typeable c, Typeable d)
      => Closure (c -> d) -> p a c -> p a d
    staticRmap sg = staticDimap (static id) sg
  
    {-# MINIMAL staticDimap | staticLmap, staticRmap #-}
  
  staticCompose
    :: (Typeable a, Typeable b, Typeable c)
    => Closure (b -> c) -> Closure (a -> b) -> Closure (a -> c)
  staticCompose f g = static (.) `cap` f `cap` g
  
  instance StaticProfunctor WrappedArrowClosure where
    staticDimap sf sg (WrapArrowClosure sk) =
      WrapArrowClosure (sg `staticCompose` sk `staticCompose` sf)
  