n-ary-functor-1.0: An n-ary version of Functor

NAryFunctor

Synopsis

# Documentation

class NFunctor f where Source #

A generalization of Functor, Bifunctor, Contravariant, Profunctor, etc.

• (NFunctor f, VarianceStack f ~ CovariantT (->) is equivalent to Functor f.
• (NFunctor f, VarianceStack f ~ CovariantT (CovariantT (->)) is equivalent to Bifunctor f.
• (NFunctor f, VarianceStack f ~ ContravariantT (->) is equivalent to Contravariant f.
• (NFunctor f, VarianceStack f ~ InvariantT (->) is equivalent to Invariant f.
• (NFunctor f, VarianceStack f ~ ContravariantT (CovariantT (->)) is equivalent to Profunctor f.

The associated type VarianceStack specifies the variance of all the type parameters using a stack of VarianceTransformers ending with (->).

Example instance:

instance NFunctor (,,) where
type VarianceStack (,,) = CovariantT (CovariantT (CovariantT (->)))
nmap = CovariantT $\f1 -> CovariantT$ \f2
-> CovariantT \$ \f3
-> \(x1,x2,x3)
-> (f1 x1, f2 x2, f3 x3)

Note that it is not possible to write an instance for a partially-applied type; for example, it is not possible to write an NFunctor ((,,) a) instance corresponding to the Functor ((,,) a) instance. Instead, the NFunctor ((,,) a) and NFunctor ((,,) a b) instances are derived from the above instance.

Laws:

nmap <#>     id       = nmap -#- () = id
nmap     >#< id       = nmap -#- () = id
nmap <#>/>#< (id, id) = nmap -#- () = id
...
nmap -#- () -#- () <#> f =
nmap        -#- () <#> f =
nmap               <#> f
(nmap <#> f1 <#> f2) . (nmap <#> g1 <#> g2) = nmap <#> (f1 . g1) <#> (f2 . g2)
(nmap >#< f1 >#< f2) . (nmap >#< g1 >#< g2) = nmap >#< (g1 . f1) >#< (g2 . f2)
...

Minimal complete definition

nmap

Associated Types

type VarianceStack f :: k -> k -> * Source #

Methods

nmap :: VarianceStack f f f Source #

Instances

 (NFunctor (k1 -> k) f, (~) ((k1 -> k) -> (k1 -> k) -> *) (VarianceStack (k1 -> k) f) (t inner), VarianceTransformer k1 k t a) => NFunctor k (f a) Source # A bold instance! We should be suspicious of any instance for f a, because it is likely to overlap with other instances. For instance, what if we want to define an NFunctor ((->) a) instance corresponding to the Functor ((->) a) instance?I claim that you will never have to write such an instance; it will always be possible to write the NFunctor (->) instance instead, and to have the NFunctor ((->) a) derived from the NFunctor (->) instance via this bold instance. If you really can't find a way to map over a type parameter, use NonvariantT to skip over it. Associated Typestype VarianceStack (f a) (f :: f a) :: k -> k -> * Source # Methodsnmap :: VarianceStack (f a) f f f Source # Source # For kind *, nmap must be the identity function. If Bifunctor and Functor correspond to binary and unary functors, this corresponds to a "nullary" functor.>>> nmap () ()  Associated Typestype VarianceStack () (f :: ()) :: k -> k -> * Source # Methodsnmap :: VarianceStack () f f f Source # NFunctor (* -> (* -> *) -> * -> *) WriterT Source # Associated Typestype VarianceStack WriterT (f :: WriterT) :: k -> k -> * Source # Methods NFunctor (* -> (* -> *) -> * -> *) StateT Source # Associated Typestype VarianceStack StateT (f :: StateT) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,,,,,,,,) (f :: (,,,,,,,,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,,,,,,,) (f :: (,,,,,,,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,,,,,,) (f :: (,,,,,,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,,,,,) (f :: (,,,,,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,,,,) (f :: (,,,,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,,,) (f :: (,,,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,,) (f :: (,,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> * -> *) (,,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,,) (f :: (,,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> * -> *) (,,,,,,) Source # Associated Typestype VarianceStack (,,,,,,) (f :: (,,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> * -> *) (,,,,,) Source # Associated Typestype VarianceStack (,,,,,) (f :: (,,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> * -> *) (,,,,) Source # Associated Typestype VarianceStack (,,,,) (f :: (,,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> * -> *) (,,,) Source # Associated Typestype VarianceStack (,,,) (f :: (,,,)) :: k -> k -> * Source # Methods NFunctor (* -> * -> * -> *) (,,) Source # Associated Typestype VarianceStack (,,) (f :: (,,)) :: k -> k -> * Source # Methodsnmap :: VarianceStack (,,) f f f Source # NFunctor (* -> * -> *) (->) Source # Associated Typestype VarianceStack (->) (f :: (->)) :: k -> k -> * Source # Methodsnmap :: VarianceStack (->) f f f Source # NFunctor (* -> * -> *) Either Source # Associated Typestype VarianceStack Either (f :: Either) :: k -> k -> * Source # Methods NFunctor (* -> * -> *) (,) Source # Associated Typestype VarianceStack (,) (f :: (,)) :: k -> k -> * Source # Methodsnmap :: VarianceStack (,) f f f Source # Source # Associated Typestype VarianceStack Identity (f :: Identity) :: k -> k -> * Source # Methods NFunctor (* -> k -> *) (Const k) Source # Associated Typestype VarianceStack (Const k) (f :: Const k) :: k -> k -> * Source # Methodsnmap :: VarianceStack (Const k) f f f Source # NFunctor (* -> (* -> *) -> * -> *) (ReaderT *) Source # Associated Typestype VarianceStack (ReaderT *) (f :: ReaderT *) :: k -> k -> * Source # Methodsnmap :: VarianceStack (ReaderT *) f f f Source #

class VarianceTransformer t a where Source #

This library uses a stack of VarianceTransformers to indicate the variance of each type parameter. Each transformer in the stack specifies the variance of one type parameter, and wraps an inner stack specifying the variance of the remaining type parameters, until we reach (->), the base of the stack.

Each VarianceTransformer is eliminated by an infix function, such as (<#>). This function takes a stack on the left, and its second argument has whatever type is necessary in order to map over the corresponding type parameter; for covariant type parameters, it will be a function of type (a -> b), for contravariant type parameters, it will be a function of type (b -> a), for invariant type parameters, it will be a pair of functions (a -> b, b -> a), etc.

The (-#-) method witnesses the fact that regardless of the variance of a given type parameter, there is always an identity-like argument which can be passed as that second argument which will cause that type parameter to be left unchanged. It takes a stack on the left, and its second argument is simply ().

Minimal complete definition

(-#-)

Methods

(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

Instances

 VarianceTransformer k1 k (NonvariantT k1 k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source # VarianceTransformer k1 k (PhantomvariantT k1 k1 k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source # VarianceTransformer * k (InvariantT k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source # VarianceTransformer * k (ContravariantT k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source # VarianceTransformer * k (CovariantT k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source # Functor m => VarianceTransformer (* -> *) k (Invariant1T k k) m Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source # Functor m => VarianceTransformer (* -> *) k (Contravariant1T k k) m Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source # Functor m => VarianceTransformer (* -> *) k (Covariant1T k k) m Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype CovariantT to f f' Source #

Constructors

 CovariantT Fields(<#>) :: forall a a'. (a -> a') -> f a to f' a'

Instances

 VarianceTransformer * k (CovariantT k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype Covariant1T to f f' Source #

Constructors

 Covariant1T Fields(<##>) :: forall m m'. (Functor m, Functor m') => (m :~> m') -> f m to f' m'

Instances

 Functor m => VarianceTransformer (* -> *) k (Covariant1T k k) m Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype ContravariantT to f f' Source #

Constructors

 ContravariantT Fields(>#<) :: forall a a'. (a' -> a) -> f a to f' a'

Instances

 VarianceTransformer * k (ContravariantT k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype Contravariant1T to f f' Source #

Constructors

 Contravariant1T Fields(>##<) :: forall m m'. (Functor m, Functor m') => (m' :~> m) -> f m to f' m'

Instances

 Functor m => VarianceTransformer (* -> *) k (Contravariant1T k k) m Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype InvariantT to f f' Source #

Constructors

 InvariantT Fields(<#>/>#<) :: forall a a'. (a -> a', a' -> a) -> f a to f' a'

Instances

 VarianceTransformer * k (InvariantT k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype Invariant1T to f f' Source #

Constructors

 Invariant1T Fields(<##>/>##<) :: forall m m'. (Functor m, Functor m') => (m :~> m', m' :~> m) -> f m to f' m'

Instances

 Functor m => VarianceTransformer (* -> *) k (Invariant1T k k) m Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype NonvariantT to f f' Source #

If you can't figure out how to map over a particular type parameter, use this variance and we'll leave it alone. The corresponding infix operator is (-#-).

Constructors

 NonvariantT FieldsunNonvariant :: forall a a'. a ~ a' => f a to f' a'

Instances

 VarianceTransformer k1 k (NonvariantT k1 k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #

newtype PhantomvariantT to f f' Source #

Phantom type parameters can be changed to any other type, no a -> b function needed, so we only ask for a (). Use (-#-) in the common case in which you don't want to change the phantom type, and (👻#👻) in the rare case in which you do want to change it.

Constructors

 PhantomvariantT Fields(👻#👻) :: forall a a'. () -> f a to f' a'

Instances

 VarianceTransformer k1 k (PhantomvariantT k1 k1 k k) a Source # Methods(-#-) :: t inner f g -> () -> inner (f a) (g a) Source #