-- | 'Closure' is not a functor, since we cannot map arbitrary functions over
-- it. But it sure looks like one, and an applicative one at that. What we can
-- do is map /static pointers to/ arbitrary functions over it (or in general,
-- closures). 'Closure' is not just an applicative functor, it's also a monad,
-- as well as a comonad, if again we limit the function space to those functions
-- that can be statically pointed to.
-- In fact an entire hierarchy of classes mirroring the standard classes can be
-- defined, where nearly the only difference lies in the fact that higher-order
-- arguments must be a proof of /static/-ness (i.e. a 'Closure'). The other
-- difference is that composing static values requires a proof of typeability,
-- so we carry those around ('Typeable' constraints).
-- This module and others define just such a class hierarchy in the category of
-- static functions (aka values of type @'Closure' (a -> b)@).

module Data.Functor.Static where

import Control.Distributed.Closure
import Data.Typeable (Typeable)

-- | Instances of 'StaticFunctor' should satisfy the following laws:
-- @
-- 'staticMap' (static 'id') = 'id'
-- 'staticMap' (static (.) ``cap`` f ``cap`` g) = 'staticMap' f . 'staticMap' g
-- @
class Typeable f => StaticFunctor f where
  staticMap :: (Typeable a, Typeable b) => Closure (a -> b) -> f a -> f b

instance StaticFunctor Closure where
  staticMap = cap