Functors in Scala
This post presents a nice overview of using functors in Scala for mapping between values.
Join the DZone community and get the full member experience.
Join For FreeWhile programming in Scala, we often come across a term called a functor. A functor is an extremely simple, but powerful concept. In this blog, we'll discuss that in more detail.
Theoretically, a functor is a type of mapping between categories. Given two categories, A and B, a functor, F, maps the objects or entities of A to the objects or entities of B. We can simply call it a function of objects or entities.
In programming, functors come into play when we have types or values wrapped inside contexts or containers. Wrapping the app up inside context blocks the application from using normal functions on the values. This happens because the result of the function is dependent on the context.
The solution to above scenario is a function that knows how to apply functions to the values wrapped in a context. Internally speaking, this function should have the potential to:
- Unwrap (fetch) the value from the context.
- Apply the function to the value.
- Re-wrap the resultant into the context.
A functor is defined by a type Constructor F[_] together with a function ...
map :(A=>B) => F[A]=>F[B]
... where the following holds true:
- Map identity means the same thing as identity.
- (Map f) compose (map g) is equal to map (f compose g).
Functor(s) are not in-built in Scala — as abstractions, they do not exist in Scala — but functor-like behavior is built into Scala. The invocations of the map on various types in Scala is consistent with the definition of functors. The example below illustrates the point:
But certain libraries, like Scalaz, provide us with the concrete concept of functors. Scalaz provides us with a type clas sFunctor[F[_]] , which defines a map as
def map[A,B](fa:F[A])(f:A=>B):F[B]
Along with a trait functor, which formulates the above-stated rules.
Let's look at an implementation with an example:
First of all, we need to import Scalaz:
import scalaz.Functor
case class Container[A](first:A,second:A)
implicit val demoFunctor= new Functor[Container]{
def map[A,B](fa:Container[A])(f:A=>B):Container[B]=Container(f(fa.first),f(fa.second))
}
There are plenty of other examples of functors, too, such as options, streams, lists, etc.
implicit val OptionFunctor =new Functor[Option] {
def fmap[A,B](f:A=>B):Option[A]=>Option[B]=option =>option map f
}
implicit val ListFunctor =new Functor[List] {
def fmap[A,B](f:A=>B):List[A]=>List[B]=list =>list map f
}
And there you have it. You learned about functors, what they can do, and how to create them. In my next blog, I'll be discussing functors and applicatives in more details.
Happy reading!
Published at DZone with permission of Pallavi Singh, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments