@hackage functormonad0.1.1.0
FFunctor: functors on (the usual) Functors
Categories
License
BSD3Clause
Maintainer
Koji Miyazato <viercc@gmail.com>
Links
 Homepage
 Documentation
 No source repository
 Changelog
Versions
 0.1.1.0 Wed, 7 Feb 2024
Installation
Tested Compilers
Dependencies (10)
 base >=4.16 && <5
 transformers >=0.6.1 && <0.7
 adjunctions >=4.4.2 && <4.5
 autoliftclasses >=1.0.1 && <1.2
 bifunctors >=5.6.1 && <5.7
 comonad >=5.0.8 && <5.1 Show all…
Dependents (0)
functormonad: Monads on category of Functors
This package provides FFunctor
and FMonad
,
each corresponds to Functor
and Monad
but higherorder.
a Functor f 
a FFunctor ff 


Takes  a :: Type 
g :: Type > Type , Functor g 
Makes  f a :: Type 
ff g :: Type > Type , Functor (ff g) 
Methods  fmap :: (a > b) > f a > f b 
ffmap :: (Functor g, Functor h) => (g ~> h) > (ff g ~> ff h) 
a Monad m 
a FMonad mm 


Superclass  Functor  FFunctor 
Methods  return = pure :: a > m a 
fpure :: (Functor g) => g ~> mm g 
(=<<) :: (a > m b) > m a > m b 
fbind :: (Functor g, Functor h) => (g ~> mm h) > (mm g ~> mm h) 

join :: m (m a) > m a 
fjoin :: (Functor g) => mm (mm g) ~> mm g 
See also: https://viercc.github.io/blog/posts/20200823fmonad.html (Japanese article)
Motivational examples
Many types defined in base and popolar libraries like
transformers take a parameter expecting a Functor
.
Here are two, simple examples.
 From "base", Data.Functor.Sum
data Sum f g x = InL (f x)  InR (g x)
instance (Functor f, Functor g) => Functor (Sum f g)
 From "transformers", Control.Monad.Trans.Reader
newtype ReaderT r m x = ReaderT { runReaderT :: r > m x }
instance (Functor m) => Functor (ReaderT r m)
These types often have a way to map a natural transformation, an arrow between two Functor
s,
over that parameter.
 The type of natural transformations
type (~>) f g = forall x. f x > g x
mapRight :: (g ~> g') > Sum f g ~> Sum f g'
mapRight _ (InL fx) = InL fx
mapRight nt (InR gx) = InR (nt gx)
mapReaderT :: (m a > n b) > ReaderT r m a > ReaderT r n b
 mapReaderT can be used to map natural transformation
mapReaderT' :: (m ~> n) > (ReaderT r m ~> ReaderT r n)
mapReaderT' naturalTrans = mapReaderT naturalTrans
The type class FFunctor
abstracts type constructors equipped with such a function.
class (forall g. Functor g => Functor (ff g)) => FFunctor ff where
ffmap :: (Functor g, Functor h) => (g ~> h) > ff g x > ff h x
ffmap :: (Functor g, Functor g') => (g ~> g') > Sum f g x > Sum f g' x
ffmap :: (Functor m, Functor n) => (m ~> n) > ReaderT r m x > ReaderT r n x
Not all but many FFunctor
instances can, in addition to ffmap
, support Monad
like operations.
This package provide another type class FMonad
to represent such operations.
class (FFunctor mm) => FMonad mm where
fpure :: (Functor g) => g ~> mm g
fbind :: (Functor g, Functor h) => (g ~> ff h) > ff g a > ff h a
Both of the above examples, Sum
and ReaderT r
, have FMonad
instances.
instance Functor f => FMonad (Sum f) where
fpure :: (Functor g) => g ~> Sum f g
fpure = InR
fbind :: (Functor g, Functor h) => (g ~> Sum f h) > Sum f g a > Sum f h a
fbind _ (InL fa) = InL fa
fbind k (InR ga) = k ga
instance FMonad (ReaderT r) where
fpure :: (Functor m) => m ~> ReaderT r m
 return :: x > (e > x)
fpure = ReaderT . return
fbind :: (Functor m, Functor n) => (m ~> ReaderT r n) > ReaderT r m a > ReaderT r n a
 join :: (e > e > x) > (e > x)
fbind k = ReaderT . (>>= runReaderT . k) . runReaderT
Comparison against similar type classes
There are packages with very similar type classes, but they are more or less different to this package.

From hkd:
FFunctor
There is a class named
FFunctor
inhkd
package too. It represents a functor from /category of type constructors/k > Type
to the category of usual types and functions.Since it is not an endofunctor, there can be no
Monad
like classes on them.Another package rank2classes also provides the same class
Rank2.Functor
. 
From mmorph:
MFunctor
,MMonad
MFunctor
is a class for endofunctors on the category ofMonad
s and monad homomorphisms. IfT
is aMFunctor
, it takes aMonad m
and constructsMonad (T m)
, and itshoist
method takes a Monad morphismm ~> n
and returns a new Monad morphismT m ~> T n
.On the other hand, this library is about endofunctors on the category of
Functor
s and natural transformations, which are similar but definitely distinct concept.For example,
Sum f
in the example above is not an instance ofMFunctor
, since there are no general way to makeSum f m
aMonad
for arbitraryMonad m
.instance Functor f => FFunctor (Sum f) instance Functor f => MFunctor (Sum f)  Can be written, but it will violate the requirement to be MFunctor

From indexcore:
IFunctor
,IMonad
They are endofunctors on the category of type constructors of kind
k > Type
and polymorphic functionst :: forall (x :: k). f x > g x
.While any instance of
FFunctor
from this package can be faithfully represented as aIFunctor
, some instances can't be an instance ofIFunctor
as is. Most notably, Free can't be an instance ofIFunctor
directly, becauseFree
needsFunctor h
to be able to implementfmapI
, the method ofIFunctor
.class IFunctor ff where fmapI :: (g ~> h) > (ff g ~> ff h)
There exists a workaround: you can use another representation of
Free f
which doesn't requireFunctor f
to be aFunctor
itself, for exampleProgram
from operational package.This package avoids the neccesity of the workaround by admitting the restriction that the parameter of
FFunctor
must always be aFunctor
. Therefore,FFunctor
gives up instances which don't takeFunctor
parameter, for example, a type constructorF
with kindF :: (Nat > Type) > Nat > Type
. 
From functorcombinators:
HFunctor
,Inject
,HBind
This package can be thought of as a more developed version of
indexcore
, since they share the base assumption. The tradeoff between this package is the same: someFFunctor
instances can only beHFunctor
via alternative representations. Same applies forFMonad
versusInject + HBind
.