Examples of Functors composition - scala

This is a follow-up to an answer to my previous question.
We know that functors compose. I can write a composition of functors List[_] and Option[_] using scalaz like this:
import scalaz._, Scalaz._
scala> val flist = Functor[List]
flist: scalaz.Functor[List] = scalaz.std.ListInstances$$anon$1#a5f0295
scala> val foption = Functor[Option]
foption: scalaz.Functor[Option] = scalaz.std.OptionInstances$$anon$1#51e43ad4
scala> flist compose foption
res0: scalaz.Functor[[α]List[Option[α]]] = scalaz.Functor$$anon$1#94c02b
scala> val f = flist compose foption
f: scalaz.Functor[[α]List[Option[α]]] = scalaz.Functor$$anon$1#610bffa0
scala> val os: List[Option[Int]] = Some(1) :: Some(2) :: None :: Nil
os: List[Option[Int]] = List(Some(1), Some(2), None)
scala> f.map(os) {_ + 1}
res1: List[Option[Int]] = List(Some(2), Some(3), None)
Is it the correct way to compose functors with scalaz ?
Could you give a real-life example of a functors composition ?

Suppose that you have a list of strings, where each string is a list of characters. By composing the two list functors, you get one functor over lists of strings. You can now map functions on characters, like, say, toUpper or toLower, to the list of strings.
Is this example realistic enough?:-)

Related

Can we reverse Applicative of List?

I'm reading about scalaz and noticed that we can make a list of Applicatives to be an Applicative of List.
def sequenceA[F[_]: Applicative, A](list: List[F[A]]): F[List[A]] = list match {
case Nil => (Nil: List[A]).point[F]
case x :: xs => (x |#| sequenceA(xs)) {_ :: _}
}
The question is can we do the opposite? Can we transform F[List[A]] to List[F[A]]?
This is possible if the F in question is Traversable. The code you're showing is specialized for List, but in fact it holds for all Traversable functors.
This means, that for every F that's Traversable and any G that's Applicative, we can go from F[G[A]] to G[F[A]] with sequence.
List also has an Applicative, so we can use it as our G, whereas in your example List was used as the F, the Traversable functor.
An example where what you're asking works could be Option. Here's the original direction:
val x: List[Option[Int]] = ...
val y: Option[List[Int]] = x.sequence
and the other direction:
val a: Option[List[Int]] = ...
val b: List[Option[Int]] = a.sequence
We could also write another function specializing to List:
def sequenceT[F[_]: Traverse, A](list: F[List[A]]): List[F[A]] = ...

Composing functions that return an option

Suppose I have a few functions of type Int => Option[Int]:
def foo(n: Int): Int => Option[Int] = {x => if (x == n) none else x.some}
val f0 = foo(0)
val f1 = foo(1)
I can compose them with >=> as follows:
val composed: Int => Option[Int] = Kleisli(f0) >=> Kleisli(f1)
Suppose now I need to compose all functions from a list:
val fs: List[Int => Option[Int]] = List(0, 1, 2).map(n => foo(n))
I can do it with map and reduce:
val composed: Int => Option[Int] = fs.map(f => Kleisli(f)).reduce(_ >=> _)
Can it (the composed above) be simplified ?
If you want the composition monoid (as opposed to the "run each and sum the results" monoid), you'll have to use the Endomorphic wrapper:
import scalaz._, Scalaz._
val composed = fs.foldMap(Endomorphic.endoKleisli[Option, Int])
And then:
scala> composed.run(10)
res11: Option[Int] = Some(10)
The monoid for kleisli arrows only requires a monoid instance for the output type, while the composition monoid requires the input and output types to be the same, so it makes sense that the latter is only available via a wrapper.
[A] Kleisli[Option, A, A] is a Semigroup via Compose, so we can use foldMap1:
val composed: Int => Option[Int] = fs.foldMap1(f => Kleisli(f))
Interestingly this doesn't work, though if we pass the correct instance explicitly then it does:
scala> val gs = NonEmptyList(fs.head, fs.tail: _*)
gs: scalaz.NonEmptyList[Int => Option[Int]] = NonEmptyList(<function1>, <function1>, <function1>)
scala> gs.foldMap1(f => Kleisli(f))(Kleisli.kleisliCompose[Option].semigroup[Int])
res20: scalaz.Kleisli[Option,Int,Int] = Kleisli(<function1>)
scala> gs.foldMap1(f => Kleisli(f))(Kleisli.kleisliCompose[Option].semigroup[Int]).apply(1)
res21: Option[Int] = None
I'm not sure where the instance that seems to take priority is coming from.

How to simplify nested map calls?

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 ?
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)))
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)
From the question I understood that you are tying to prune the list iterator e.i. remove upper levels of list in that case you can use flatten which convert list of lists into a single list.
I will be removing few layers of list using flatten
Code:-
val lists = List(
List(
List(
List("1"),List("2")
),
List(
List("3"),List("4")
) ,
List(
List("a"),List("b")
),
List(
List("c"),List("d")
)
)
)
val innerVal = lists.flatten.foreach(println)
results :-
List(List(1), List(2))
List(List(3), List(4))
List(List(a), List(b))
List(List(c), List(d))

Scala Applicatives?

In Scala, how can I append an Option[A] to Option[A]:
Meaning:
Some("foo") ??? Some("bar") == Some("foobar")
In Haskell I'd use an applicative:
ghci>import Control.Applicative
ghci> (++) <$> (Just "foo") <*> (Just "bar")
Just "foobar"
Are there Applicatives in Scala's standard Typesafe library?
With scalaz you can do it this way:
import scalaz.syntax.applicative._
import scalaz.std.option._
val l: Option[String] = Some("foo")
val r: Option[String] = Some("bar")
val result = ^(l, r)(_ + _)
println(result) // Some("foobar")
Applicatives aren't in the standard library, but you can use for-comprehensions like monads in Haskell:
for {
l <- Some("foo")
r <- Some("bar")
} yield (l + r)
(or rewrite it with flatMap, of course). Otherwise, go with scalaz, as in Eugene's answer.
If you just want to achieve this particular syntax, you can combine an implicit class with a monad for-comprehension:
implicit class RichOption(a: Option[String]) {
def ???(b: Option[String]) = for (sa <- a; sb <- b) yield sa+sb
}
scala> Some("foo") ??? Some("bar") == Some("foobar")
res4: Boolean = true

Converting a tuple of options to an option of tuple with Scalaz or Shapeless

Having
(Some(1), Some(2))
I expect to get
Some((1, 2))
and having
(Some(1), None)
I expect to get
None
I realize you're asking about Scalaz, but it's worth pointing out that the standard method is not unbearably wordy:
val x = (Some(1), Some(2))
for (a <- x._1; b <-x._2) yield (a,b)
In the general case (e.g. arbitrary-arity tuples), Shapeless is best at this sort of thing.
You can use the fact that Scalaz 7 provides a Bitraverse instance for tuples and then sequence as usual (but with bisequence instead of sequence):
scala> import scalaz._, std.option._, std.tuple._, syntax.bitraverse._
import scalaz._
import std.option._
import std.tuple._
import syntax.bitraverse._
scala> val p: (Option[Int], Option[String]) = (Some(1), Some("a"))
p: (Option[Int], Option[String]) = (Some(1),Some(a))
scala> p.bisequence[Option, Int, String]
res0: Option[(Int, String)] = Some((1,a))
Unfortunately Scalaz 7 currently needs the type annotation here.
In a comment Yo Eight states that the type annotation will remain mandatory here. I'm not sure what his or her reasoning is, but it's in fact perfectly easy to write your own wrapper that will provide any appropriately typed tuple with a bisequence method and won't require a type annotation:
import scalaz._, std.option._, std.tuple._
class BisequenceWrapper[F[_, _]: Bitraverse, G[_]: Applicative, A, B](
v: F[G[A], G[B]]
) {
def bisequence = implicitly[Bitraverse[F]].bisequence(v)
}
implicit def bisequenceWrap[F[_, _]: Bitraverse, G[_]: Applicative, A, B](
v: F[G[A], G[B]]
) = new BisequenceWrapper(v)
Now (some(1), some("a")).bisequence will compile just fine.
I can't think of a good reason Scalaz wouldn't include something like this. Whether or not you want to add it in the meantime is a matter of taste, but there's definitely no theoretical obstacle to letting the compiler do the typing here.
I think that cats version will not be redundant here.
# import cats.implicits._
import cats.implicits._
# (4.some, 2.some).bisequence
res1: Option[(Int, Int)] = Some((4, 2))
# (4.some, none).bisequence
res2: Option[Tuple2[Int, Nothing]] = None
Starting Scala 2.13, this exact behavior is provided in the standard library by Option#zip:
Some(2) zip Some('b') // Some((2, 'b'))
Some(2) zip None // None
None zip Some('b') // None
None zip None // None
Before Scala 2.13, Option#zip was returning an Iterable and it was possible to combine it with headOption:
Some(2) zip Some('b') headOption // Some((2, 'b'))
Some(2) zip None headOption // None
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> (Tuple2.apply[Int, Int] _).lift[Option].tupled
res5: (Option[Int], Option[Int]) => Option[(Int, Int)] = <function1>
scala> res5((some(3), some(11)))
res6: Option[(Int, Int)] = Some((3,11))
scala> res5((some(3), none))
res7: Option[(Int, Int)] = None