Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simplify nested map calls?

Tags:

functor

scala

Suppose I have a few nested functors, e.g. List[Option[Int]] and need to call the map of the most inner one.

Now I am using nested maps:

scala> val opts: List[Option[Int]] = List(Some(0), Some(1))
opts: List[Option[Int]] = List(Some(0), Some(1))

scala> opts.map(o => o.map(_ + 1))
res0: List[Option[Int]] = List(Some(1), Some(2))

What if I have 3 nesting levels, for instance ?
Is there any simple alternative to nested maps ?

like image 906
Michael Avatar asked Jul 08 '15 05:07

Michael


People also ask

What is the best way to use nested maps?

Nested maps work well when you need to rapidly find all the variations, kinds, and subtypes of type A. For example, choosing A (vs. B, C, ...) might be the first step in a decision tree. Once the user or algorithm or whatever picks A, then you need to know only about A's subtypes, and B..Z or B..ZZZZZ no longer matter.

What is the difference between a nested HashMap and regular map?

The only difference between a nested and regular Map is that the values of a nested HashMap are Map type: 5. Comparing Nested HashMap s There are many ways to compare HashMap s in Java. We can compare them using the equals () method. The default implementation compares each value. If we change the inner Map's contents, the equality check fails.

What is map simplification in math?

Map simplification may be regarded as a pictorial arrangement of the truth table which allows an easy interpretation for choosing the minimum number of terms needed to express the function algebraically. The map method is also known as Karnaugh map or K-map. Each combination of the variables in a truth table is called a mid-term.

How to use JavaScript map () method to access nested objects?

How to use JavaScript map () method to access nested objects? Use map () along with typeOf to access nested objects. Following is the code − node fileName.js.


2 Answers

Yes, this is possible with scalaz.Functor:

scala> import scalaz.Functor
import scalaz.Functor

scala> import scalaz.std.list._
import scalaz.std.list._

scala> import scalaz.std.option._
import scalaz.std.option._

scala> Functor[List].compose[Option].map(List(some(0), some(1)))(_ + 1)
res1: List[Option[Int]] = List(Some(1), Some(2))

However, this is longer than to simply call map with a nested map. If you often map nested structures, you can create helper functions:

def map2[F[_], G[_], A, B](fg: F[G[A]])(f: A => B)
  (implicit F0: Functor[F], G0: Functor[G]): F[G[B]] =
  F0.map(fg)(g => G0.map(g)(f))

def map3[F[_], G[_], H[_], A, B](fg: F[G[H[A]]])(f: A => B)
  (implicit F0: Functor[F], G0: Functor[G], H0: Functor[H]): F[G[H[B]]] =
  F0.map(fg)(g => G0.map(g)(h => H0.map(h)(f)))

...

Usage:

scala> map2(List(some(0), some(1)))(_ + 1)
res3: List[Option[Int]] = List(Some(1), Some(2))

scala> map3(List(some(some(0)), some(some(1))))(_ + 1)
res4: List[Option[Option[Int]]] = List(Some(Some(1)), Some(Some(2)))
like image 127
ZhekaKozlov Avatar answered Oct 05 '22 12:10

ZhekaKozlov


If you have a lot of nested functors and you don't want to flatten them (i.e. they're not monads or you don't want to use them as monads) - then lenses may help. There is quicklens implementation, which supports traversable lenses : http://www.warski.org/blog/2015/03/quicklens-traversing-options-and-lists/.

Example (sorry didn't try to compile it):

modify(opts)(_.each.each).using(_ + 1)

Anyway, you have to specify nesting level, but you don't have to nest functions here. And it's enough to specify it once, like (conceptual example, didn't check):

def md2[T]: (l: List[Option[T]]) => modify(l)(_.each.each)

md2[Int](opts).using(_ + 1)     
like image 29
dk14 Avatar answered Oct 05 '22 12:10

dk14