While reading the description of Functors on this blog:
https://hseeberger.wordpress.com/2010/11/25/introduction-to-category-theory-in-scala/
there is a generic definition of Functor and a more specific one:
trait GenericFunctor[->>[_, _], ->>>[_, _], F[_]] {
def fmap[A, B](f: A ->> B): F[A] ->>> F[B]
}
trait Functor[F[_]] extends GenericFunctor[Function, Function, F] {
final def fmap[A, B](as: F[A])(f: A => B): F[B] =
fmap(f)(as)
}
Clearly this means Functors can be used with other higher-kinded types besides Function objects. Could someone please give an example or explain how or why or in what scenario that would be done? Namely, what would another implementation of GenericFunctor be in Scala -- that uses a different type constructor from Function? Thanks!
EDIT:
Just to clarify:
object Functor {
def fmap[A, B, F[_]](as: F[A])(f: A => B)(implicit functor: Functor[F]): F[B] =
functor.fmap(as)(f)
implicit object ListFunctor extends Functor[List] {
def fmap[A, B](f: A => B): List[A] => List[B] =
as => as map f
}
}
scala> fmap(List(1, 2, 3))(x => x + 1)
res0: List[Int] = List(2, 3, 4)
Just to clarify, according to my understanding ListFunctor implements the 1-arg fmap in GenericFunctor while the code in the repl transcript calls the fmap in Trait Functor, which in turn calls an fmap implementation (e.g. in ListFunctor).
This doesn't change the overall question, just thought it would help people trying to provide answers. Any insights provided would be appreciated.
In your example
Functor
is an endofunctor in the category of Scala types withFunction1
as arrows.There are other categories. For example, imagine a category in which the objects are Scala types, and there is an arrow
A >~> B
ifB
is a subtype ofA
. This category in Scalaz is calledLiskov
. There is a "forgetful" functor from theLiskov
category to theFunction1
category:Note that you can build some interesting functors by fixing one or more of the arguments to
GenericFunctor
. For example...A constant functor maps every object in one category to a single object in another:
An endofunctor maps a category to itself:
An identity functor maps every object and arrow to itself:
And of course, your
Functor
trait is just anEndoFunctor
in theFunction1
category.You can imagine a functor which lifts an instance of
Either[A,B]
into anEither[F[A],F[B]]
whereF
can be aList
,Option
, etc.EDIT Implementation example:
EDIT2 Another (maybe useful) example is with a functor with goes from a
PartialFunction
(type->>
) to aFunction
(type->>>
):This second example allows to implement the
collect
operation as defined in Scala collections:Data.Category
is a good source for examples of things like this (in Haskell). Partially translating one of the instances from http://hackage.haskell.org/packages/archive/data-category/0.4.1/doc/html/src/Data-Category-Functor.html: