Disclaimer: this is a part of a homework assignment.
I want to implement the flatMap for the custom List object. I have successfully implemented map, but I have problem with flatMap. I do not know how to flatten the List of Lists that I get from map. I do not know if I really should use map at all.
trait List[+A] {
/** The first element */
def head: A
/** The rest of the elements */
def tail: List[A]
def flatMap[B](f: A => List[B]): List[B]
def map[B](f: A => B): List[B]
// Concatenate two lists
def concat[B >: A](that: List[B]): List[B] = this match {
case Empty => that
case NonEmpty(head, tail) => NonEmpty(head, tail concat that)
}
}
case object Empty extends List[Nothing] {
def head = throw new UnsupportedOperationException("Empty.head")
def tail = throw new UnsupportedOperationException("Empty.tail")
def flatMap[B](f: Nothing => List[B]): List[B] = Empty
def map[B](f: Nothing => B): List[B] = Empty
override def toString = "Empty"
}
case class NonEmpty[A](head: A, tail: List[A]) extends List[A] {
def map[B](f: A => B): List[B] = {
NonEmpty(f(head), tail.map(f))
}
def flatMap[B](f: A => List[B]): List[B] = {
val a = this.map(f)
for (x <- a; y <- x) yield y
}
}
as this is a homework, I don't want to give you a complete solution, just some hints.
You don't need map to implement flatMap (actually it is easier to do it the other way around)
you have everything you need (flatMap takes a function that returns a List[B] and List has concat defined)
implement the flatMap of Empty first ;-)
You have to write flatMap for a list with length n. Try to solve it supposing that you have already solved it for a list with length n-1. If you can do this, then you solved the problem, because n => n-1 => ... => 1 => 0, and for 0 you already has a solution.
This kind of thinking is suitable for your List, because it is a recursive type.
You did this already with map, do the same with flatMap. Both function is a transformation from List[A] to List[B], the only difference is the tool what they can use, map has a function that converts A to B, while flatMap has a function that converts A to List[B]
Related
I am trying to find an implementation for this Scala function signature:
def explode[A, B](f: A => List[B]): List[A => B]
The opposite direction is possible:
def nest[A, B](fs: List[A => B]): A => List[B] = (a: A) => fs.map(_(a))
By now I am tending to believe the first one (explode) is unimplementable, but I am happy to be proven wrong. If it is indeed not possible to implement, is there a deep reasoning behind it?
In my view, I am essentially asking the compiler to "duplicate" that input A some n times (the Lists size), and "fix" it as input.
In my view, I am essentially asking the compiler to "duplicate" that input A some n times (the Lists size), and "fix" it as input.
The problem is you don't know what n is. Consider for example a function that returns a list of all the prime divisors of a number:
def divisors(n: Int): List[Int] = ???
What do you expect explode(divisors) to be? divisors can return a List of any size, depending on its argument, whenever it's invoked in the future. But when you call explode it has to return a List of a fixed size immediately.
Given a fixed type A, the signatures in your code can be written like this:
type F[T] = List[T]
type G[T] = A => T
def nest[B]: F[G[B]] => G[F[B]]
def explode[B]: G[F[B]] => F[G[B]]
nest and explode are reminiscent to sequence operation. It works for nest, because it's possible to write a Traverse instance for a List, but it's not possible to write a Traverse instance for a function A => T. Here is an equivallent question for Haskell, that gives some more insight.
If you want to make some implementation that just satisfies the signature you can do something like this:
def explode[A, B](f: A => List[B]): List[A => B] = {
Nil
}
def explode[A, B](f: A => List[B]): List[A => B] = {
List(f.andThen(_.head))
}
But I guess you want something semantically different:
"duplicate" that input A some n times (the Lists size), and "fix" it
as input
In that case, there is a problem. The result of f, in the general case, depends on the input A. It could be Nil, finite-size list, or infinite list.
What you can do is only something like:
def explode[A, B](f: A => List[B]): A => List[A => B] = {
f.andThen(_.map(b => (_: A) => b)
}
I am walking through the 'Functional Programming in Scala' exercises and in chapter 4 there is this one piece of code about the Option class that I think I am having troubles to understand.
I am asked to implement flatMap. I know that Map is meant to transform an A to a B, and then wrap it in an Option. So what even is the purpose of flatMap? If I recall correctly, flatMap implemented in lists is meant to take a function that would transform A to a List of a B. A => List[B]. In principle, I imagine that applies here as well. That Option is just a list with one element and I am to give it a function that is meant to take an A and wrap it inside of an Option.
I don't know how I would implement flatMap using Map. The apparent implementation is as simple as:
def flatMap(f: A => Option[B]): Option[B] = map(f) getOrElse None
Why does this implementation work? f does not have the type signature of A=>B, yet it calls map just fine with this signature. Obviously calling getOrElse(None) is what makes it work, because if I take that out the implementation starts to complain. But I don't understand why the scala interpreter is not complaining here. We know that f returns an Option[B]. Is That returned Option calling getOrElse, which is then unwrapping its value so it can have the right type signature? If this is the case, are there other ways to write this that would be more obvious as to why it would work?
def flatMap[B](f: A => Option[B]): Option[B] =
map((a)=> f(a).getOrElse(None)) // doesn't work
Unfortunately this book does not really provide an in depth introduction to scala so I am not sure if this is syntax(pretty sure its syntactical) or logic that I am not understanding.
import scala.{Option => _, Some => _, Either => _, _} // hide std library `Option`, `Some` and `Either`, since we are writing our own in this chapter
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case Some(a) => Some(f(a))
case None => None
}
def getOrElse[B>:A](default: => B): B = this match {
case None => default
case Some(b) => b
}
def flatMap[B](f: A => Option[B]): Option[B] =
map(f) getOrElse(None)
def orElse[B>:A](ob: => Option[B]): Option[B] = ???
def filter(f: A => Boolean): Option[A] = ???
}
case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]
object Option {
def mean(xs: Seq[Double]): Option[Double] =
if (xs.isEmpty) None
else Some(xs.sum / xs.length)
def variance(xs: Seq[Double]): Option[Double] = ???
def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] = ???
def sequence[A](a: List[Option[A]]): Option[List[A]] = ???
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = ???
}
Your intuition as to the meaning of flatMap is perfectly correct. I believe your confusion regarding the implementation stems from the fact that B is a type parameter defined per method, and as such, it doesn't have to be have the same value when one method calls the other.
To show this, let's simply give the type parameters of these methods different names:
def map[B](f: A => B): Option[B] = this match {
case Some(a) => Some(f(a))
case None => None
}
def getOrElse[C>:A](default: => C): C = this match {
case None => default
case Some(b) => b
}
def flatMap[D](f: A => Option[D]): Option[D] = {
map(f) getOrElse None
}
Now:
flatMap has a type parameter D, which can be anything.
When flatMap calls map, it assigns Option[D] as the value of map's type parameter B (!). So as far as map is concerned, it was passed a function f into some type B, which is actually Option[D] for some type D (but map doesn't care!)
When flatMap calls getOrElse - a similar thing happens, this time getOrElse's type parameter C gets assigned the value Option[B] - and again, getOrElse just "does its thing" without caring that the output happens to be an Option itself
This way, the returned value is:
None if the original input was None (because getOrElse would return the default it was passed)
None if f returned None (because getOrElse would return the value in the Some that it got, which itself is a None)
Some(v) if both the input and the result of f were Some
Which is exactly what flatMap should do.
we are creating our own OptionT of cats for understanding, how monads are work and monads transformation flow. While creating our own custom monad getting some of the errors. First thing below is our code:
case class WhateverOpt[W[_], A] (value: W[Option[A]]) {
def map[B] (f: A => B) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.map(value)(_.map(f)))
def flatMap[B] (f: A => WhateverOpt[W, B]) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.flatMap(value)(optA => optA match {
case Some(v) => f(v).value
}))
}
implicit val optionTMonad = new Monad[Option] {
override def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
override def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f)
}
val optionResult = for {
user <- WhateverOpt(repository.getUserOption(1))
addres <- WhateverOpt(repository.getAddressOption(user))
} yield addres.city
Below are the points, where we stuck:
How to handle None case in WhateverOpt flatMap method?
When executing the code, getting runtime error:
Error:(26, 12) could not find implicit value for parameter M: usercases.mtransfomer.Monad[scala.concurrent.Future]
addres <- WhateverOpt(repository.getAddressOption(user))
We are not sure about the error because we are creating optionTMonad implicit and by default, all are in the same scope. How can we resolve these two issues?
Update
Full code is available on Github branch https://github.com/harmeetsingh0013/fp_scala/blob/master/src/main/scala/usercases/mtransfomer/Example5.scala
About how to deal with None:
case class WhateverOpt[W[_], A] (value: W[Option[A]]) {
def map[B] (f: A => B) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.map(value)(_.map(f)))
def flatMap[B]
(f: A => WhateverOpt[W, B])
(implicit wMonad: Monad[W])
: WhateverOpt[W, B] = {
WhateverOpt(wMonad.flatMap(value) { (oa: Option[A]) =>
oa match {
case None => wMonad.pure(None)
case Some(a) => f(a).value
}
})
}
}
Imagine for a second that W is Future. Then the above code says:
wait until the wrapped value yields a result oa of type Option[A]
If oa turns out to be None, then there is nothing we can do, because we cannot obtain any instances of type A in order to call f. Therefore, immediately return None. The immediately return is the pure-method of the Future-monad, so for the general case we have to invoke wMonad.pure(None).
If oa yields Some(a), we can give this a to f, and then immediately unpack it to get to the value of type W[Option[B]].
Once we have the W[Option[B]] (whether empty or not), we can wrap it into WhateverOpt and return from the flatMap method.
I assume that you wanted to reimplement Monad[Option] just for fun (it's already in the library (the catsStdInstancesForOption thing is a CommutativeMonad), but here is how you could re-build it:
implicit val optionTMonad = new Monad[Option] {
override def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f)
def pure[A](a: A): Option[A] = Some(a)
def tailRecM[A, B](a: A)(f: (A) => Option[Either[A, B]]): Option[B] = {
f(a) match {
case Some(Left(nextA)) => tailRecM(nextA)(f)
case Some(Right(res)) => Some(res)
case None => None
}
}
}
Notice that 1.0.1 requires to implement pure and tailRecM, and does not provide default implementations for that.
I don't want to say much about the necessary imports for future, but the latest version has cats.instances.future which provides a Monad instance. Check this again, because it seems as if you are using a different version of cats (your version didn't complain because of the missing tailRecM in your Option-monad).
How to handle None case in WhateverOpt flatMap method?
This answer is already explained by #Gabriele Petronella and #Andrey Tyukin with details.
When executing the code, getting runtime error: Error:(26, 12) could
not find implicit value for parameter M:
usercases.mtransfomer.Monad[scala.concurrent.Future] addres <-
WhateverOpt(repository.getAddressOption(user))
This error occurs, because In WhateverOpt constructor we know that our value is W[Option[A]], where Option is already defined and handle by the code, but repository.getUserOption(1) return Future[Option[User]] where Future is handled by generic parameter W and in that, case, we need to define, how to handle monads for Future. For resolving that issue, we need to implement new Monad[Future] rather than, new Monad[Option] as below:
case class WhateverOpt[W[_], A] (value: W[Option[A]]) {
def map[B] (f: A => B) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.map(value)(_.map(f)))
def flatMap[B] (f: A => WhateverOpt[W, B]) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.flatMap(value)(optA => optA match {
case Some(v) => f(v).value
case None => M.pure(None)
}))
}
implicit val futureMonad = new Monad[Future] {
override def pure[A](a: A): Future[A] = Future.successful(a)
override def map[A, B](fa: Future[A])(f: A => B): Future[B] = fa.map(f)
override def flatMap[A, B](fa: Future[A])(f: A => Future[B]): Future[B] = fa.flatMap(f)
}
val optionResult: WhateverOpt[Future, String] = for {
user <- WhateverOpt(repository.getUserOption(1))
addres <- WhateverOpt(repository.getAddressOption(user))
} yield addres.city
I am not sure about my disription, which I mention in answere, but current my assumptions are this and for me above code is working fine. For a complete example, please click on the GitHub repo, which is mention in the question.
How to handle None case in WhateverOpt flatMap method?
When you flatMap over None you return None. When you flatMap over WhateverOpt[W[_], B] you want to return the pure of it, which in your code would be M.pure(None).
When executing the code, getting runtime error: Error:(26, 12) could not find implicit value for parameter M: usercases.mtransfomer.Monad[scala.concurrent.Future]
addres <- WhateverOpt(repository.getAddressOption(user))
That's a compile-time error (not a runtime one) and it's due to the missing instance of Monad[Future]. In order to get an instance of Monad[Future] in scope with cats, you can do:
import cats.instances.future._
import scala.concurrent.ExecutionContext.Implicits.global
Also, you can avoid declaring your own Monad[Option] by importing it from cats with
import cats.instances.option._
Maybe I don't understand some fundamentals, but what is the signature of flatMap in general? Let's imagine I'd like to implement type T supporting for expression, then I required map, flatmap and withFilter implemented by T. Is there any interface of something like that?
More precisely what is the source of the signature:
class T[+A] {
def flatMap[B](f: (A) => T[B]): T[B]
}
Or is it a definition? May I implement flatmap with different signature?
In general flatMap has signature:
class T[+A] {
def flatMap[B](f: (A) ⇒ T[B]): T[B]
def map[B](f: (A) ⇒ B): T[B]
}
For example for Option:
def flatMap[B](f: (A) ⇒ Option[B]): Option[B]
For Seq:
def flatMap[B](f: (A) ⇒ Seq[B]): Seq[B]
Of course in scala API you will see other signatures for Seq, List - because there is generic signature in trait TraversableLike for all collections.
For monad function map should:
m map f == m flatMap (x => unit(f(x)))
Where unit unit(x) = single(x), for example:
List is a monad with unit(x) = List(x)
Set is monad with unit(x) = Set(x)
Option is a monad with unit(x) = Some(x)
Update
There is no interface for flatMap/map. See example (copy to your REPL):
class C[+A](val a:A) {
def flatMap[B](f:(A) => C[B]):C[B] = f(a)
def map[B](f:(A)=>B):B = f(a)
}
Then call in REPL for method:
scala> for { k<- new C(3)} yield {k}
res2: Int = 3
No special interface needed.
But if so you can implement FilterMonadic[+A, +Repr] generic interface.
Update
SLS - 6.19 For Comprehensions and For Loops.
Methods: map, withFilter, flatMap, and foreach - can be implemented in different
ways for different carrier types. Code:
class A {
def map(f: Int => Boolean): Boolean = f(10)
def flatMap(f: Int => Boolean): Boolean = f(20)
}
for(x <- new A; y <- new A) yield x == y
And
class T[+A] {
def flatMap[B](f: (A) ⇒ T[B]): T[B]
}
is not single way to define flatMap method.
I need to implement my own List class in Scala. I've implemented:
trait List[+A] {
/** The first element */
def head: A
/** The rest of the elements */
def tail: List[A]
def map[B](f: A => B): List[B]
def flatMap[B](f: A => List[B]): List[B]
def filter(f: A => Boolean): List[A]
// Concatenate two lists
def concat[B >: A](that: List[B]): List[B] = this match {
case Empty => that
case NonEmpty(head, tail) => NonEmpty(head, tail concat that)
}
}
/** The empty list, also known as Nil */
case object Empty extends List[Nothing] {
def head = throw new UnsupportedOperationException("Empty.head")
def tail = throw new UnsupportedOperationException("Empty.tail")
def map[B](f: Nothing => B): List[B] = Empty
def flatMap[B](f: Nothing => List[B]): List[B] = Empty
def filter(f: Nothing => Boolean): List[Nothing] = Empty
override def toString = "Empty"
}
And now I need to implement filter, flatMap and Map methods:
case class NonEmpty[A](head: A, tail: List[A]) extends List[A] {
//def map[B](f: A => B): List[B] = ???
//def flatMap[B](f: A => List[B]): List[B] = ???
def filter(predicate: A => Boolean): List[A] = {
}
For instance method filter(predicate: A => Boolean): List[A] how can I iterate through every element in this list? How can I check if given predicate is true or false? (tried if(predicate(head)) - doesn't work for some reason.)
Thank you for help.
You need to traverse the elements with head and tail:
def filter(f: A => Boolean): List[A] = {
def loop(xs: List[A], ys: List[A]): List[A] =
if (xs == Empty) ys else loop(xs.tail, if (f(xs.head)) NonEmpty(xs.head, ys) else ys)
loop(this, Empty).reverse
}
This implementation can be defined in List. The last thing you need for this is the reverse method. You can implement it the same way as filter - use an inner method to traverse all elements.
Instead of reverse you can use a non-tail-recursive implementation, which must not reversed and can be implemented in the subclasses:
def filter(f: A => Boolean): List[A] =
if (f(head)) NonEmpty(head, tail filter f)
else tail filter f
The other methods can be defined in a similar way.
Often, recursion gets easier when you just live in Fairyland and pretend (almost) everything already works.
Suppose filter already did what you asked, how would you use filter to make it work for yet another element?
Well, you can decide whether you want to to include the first element of your list (depending on f), and let filter, "which already works", handle the rest. Then just concatenate the list.
def filter(f: A => Boolean) : List[A] = {
if (f(head)) NonEmpty(head, tail.filter(f))
else tail.filter(f)
}