Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Functors in Scala

DZone's Guide to

Functors in Scala

This post presents a nice overview of using functors in Scala for mapping between values.

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

While 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.

functor is defined by a type Constructor F[_] together with a function ...

map :(A=>B) => F[A]=>F[B]

... where the following holds true:

  1. Map identity means the same thing as identity.
  2. (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:

one

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!

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
java ,jvm ,scala ,functors ,design

Published at DZone with permission of Pallavi Singh, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}