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.
Related
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._
def isEven(x: Int) =
if (x % 2 == 0) x.successNel else "not even".failureNel
In the above code, the return type of isEven is inferred as scalaz.Validation[scalaz.NonEmptyList[_ <: String],Int]
Whereas explicitly specifying the return type works,
def isEven(x: Int): ValidationNel[String, Int] =
if (x % 2 == 0) x.successNel else "not even".failureNel
Can someone explain what's going on behind the scenes here? Is this a limitation of Scala's type inference system?
I'm trying to use the above function in the following expression,
(isEven(4) |#| isEven(6) |#| isEven(8) |#| isEven(10)) {_ + _ + _ + _}
and only the second variant (with explicit return type) works.
scalaz.NonEmptyList[String] is a sub type of scalaz.NonEmptyList[_ <: String], meaning scalaz.ValidationNEL[String,Int] is a sub type of scalaz.Validation[scalaz.NonEmptyList[_ <: String],Int]. The compiler just give you a more precise type in this case...
Edit: the raisin bread operator requires an Applicative instance. In this case I suppose that scalaz provide such instance for ValidationNel[String, ?], but not for the more precise type inferred for your isEven.
A simpler manifestation of that can be observed with Option:
val some = Some(1)
val none = None
(some |#| none)(_ + _) // Cannot find implicit Applicative[Some] :(
You can view that as an intersect limitation of local type inference. You could also say that FP doesn't always play well with OO. I would suggest following good practices and annotate all your public method and implicits with explicit types.
I will try to explain more details about :
why scalaz.Validation[scalaz.NonEmptyList[_ <: String],Int] this can not work with |#|?
isEven(4) |#| isEven(6) ...
First of all isEven(4) is trying to implicitly convert it from Validation[+E, +A] type to ApplyOps[F0.M,F0.A]type with |#| operator. as the implicit method in ApplySyntax:
implicit def ToApplyOpsUnapply[FA](v: FA)(implicit F0: Unapply[Apply, FA]) =
new ApplyOps[F0.M,F0.A](F0(v))(F0.TC)
As the above code, for this implicit conversion, we also need an implicitly F0: Unapply[Apply, FA] variable. for UnApply implicits, it's in the UnApply:
implicit def unapplyMFA[TC[_[_]], M0[_[_], _], F0[_], A0](implicit TC0: TC[M0[F0, ?]]): Unapply[TC, M0[F0, A0]] {
type M[X] = M0[F0, X]
type A = A0
} =
new Unapply[TC, M0[F0, A0]] {
type M[X] = M0[F0, X]
type A = A0
def TC = TC0
def leibniz = refl
}
As the Validation type, it's using the unapplyMFA implicits variable. In there we also found it's looking for another implicits TC0: TC[M0[F0, ?]] variable. as the before ToApplyOpsUnapply, In there TC0 will be Apply type, that's also can be Applicative type. so it will try to look for the Validation to Applicative implicits, it's in the Validation.scala
implicit def ValidationApplicative[L: Semigroup]: Applicative[Validation[L, ?]] =
new Applicative[Validation[L, ?]] {
override def map[A, B](fa: Validation[L, A])(f: A => B) =
fa map f
def point[A](a: => A) =
Success(a)
def ap[A, B](fa: => Validation[L, A])(f: => Validation[L, A => B]) =
fa ap f
}
for the Semigroup definition:
trait Semigroup[F] { self => //F is invariant, unlike Option[+A]
So the problem is: F is type invariant, not like the Option[+A], compiler could not find an appropriate Applicative implicits for this type Validaiton.
There is a small demo for how to enable type variant for this:
def isEven(x: Int): Validation[NonEmptyList[_ <: String], Int] =
if (x % 2 == 0) x.successNel else "not even".failureNel
val res: String = foo(isEven(4))
def foo[FA](v: FA)(implicit F0: Unapply[Apply, FA]): String = "foo bar"
implicit def ValidationApplicative[L]: Applicative[Validation[L, ?]] =
new Applicative[Validation[L, ?]] {
override def map[A, B](fa: Validation[L, A])(f: A => B) =
fa map f
def point[A](a: => A) =
Success(a)
def ap[A, B](fa: => Validation[L, A])(f: => Validation[L, A => B]) =
//fa ap f
null
}
In there we just unbind L from Semigroup, so now this is type variant. just for fun;).
I saw the below code on SO. But the problem it has is that it's map and flatMap definitions aren't fully correct. map must be able to transform the inside value of a monadic container/context, and the same way a flatMap should take a value, transform it and put it back in the monadic context/container. In the example below it's taking an A and giving an A or M[A] (instead of A->B or A->M[B])
trait Mine[A] {
def get(): A
def map(f: A => A): Mine[A]
def flatMap(f: A => Mine[A]): Mine[A]
}
case class Attempt1[A, B](a: (A, B)) extends Mine[(A, B)] {
def get(): (A, B) = a
def map(f: ((A, B)) => (A, B)): Mine[(A, B)] = {
Attempt1(f(a._1, a._2))
}
def flatMap(f: ((A, B)) => Mine[(A, B)]): Mine[(A, B)] = {
f(a._1, a._2)
}
}
So I thought of changing it and that's where I got stuck. The below code is failing for all the right reasons but can someone guide on how to implement something similar?
trait Opt[A] {
def map[B](f: A => B): Opt[B]
def flatMap[B](f: A => Opt[B]): Opt[B]
}
case class Osome[A, B](a: (A, B)) extends Opt[(A, B)] {
def flatMap[C, D](f: ((A, B)) => Opt[(C,D)]): Opt[(C, D)] = {
f(a._1, a._2)
}
def map [C, D] (f: ((A, B)) => (C, D)): Opt[(C, D)] = {
Osome(f(a._1, a._2))
}
}
The problem is, that you don't implement the map and flatMap methods of Opt in your Osome class, but you overload them. In your trait they both have one type parameter, but in your implementation they have two. Aside from that, your Osome would anyway not be a monad, as it restricts the resulting type of map and flatMap, where monads allow for arbitrary types.
I have a monad that is very similar to a collection monad. I'm currently trying to implement a monad transformer for it, but I'm failing.
I've looked at the ListT implementation in Scalaz 6 and 7, but I cannot understand how it works. It uses some additional type Step, whose purpose is unclear to me.
So can someone please explain to me how to implement a list monad transformer, either by explaining the Scalaz approach or using a different implementation?
I am not quite sure, what the Step means in scalaz, but implementing a ListT is pretty straight forward. Depending on how many operations you want to put on it, it can be a little work, but the basic monad operations can be implemented as follows.
First we need typeclasses for monad and functor (we could also add applicative, but that is not necessary for this example):
trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}
trait Monad[F[_]] extends Functor[F] {
def flatMap[A,B](fa: F[A])(f: A => F[B]): F[B]
def pure[A](x: A): F[A]
}
object Monad {
implicit object ListMonad extends Monad[List] {
def map[A,B](fa: List[A])(f: A => B) = fa map f
def flatMap[A,B](fa: List[A])(f: A => List[B]) = fa flatMap f
def pure[A](x: A) = x :: Nil
}
implicit object OptionMonad extends Monad[Option] {
def map[A,B](fa: Option[A])(f: A => B) = fa map f
def flatMap[A,B](fa: Option[A])(f: A => Option[B]) = fa flatMap f
def pure[A](x: A) = Some(x)
}
def apply[F[_] : Monad]: Monad[F] = implicitly[Monad[F]]
}
Once we have those, we can create the transformer, which basically just wraps the F[List[A]] and forwards the call to its map and flatMap function to the list by calling map on the containing functor and then calling map or flatMap resp. on the contained List/s.
final case class ListT[F[_] : Monad, A](fa: F[List[A]]) {
def map[B](f: A => B) = ListT(Monad[F].map(fa)(_ map f))
def flatMap[B](f: A => ListT[F, B]) = ListT(Monad[F].flatMap(fa) { _ match {
case Nil => Monad[F].pure(List[B]())
case list => list.map(f).reduce(_ ++ _).run
}})
def ++(that: ListT[F,A]) = ListT(Monad[F].flatMap(fa) { list1 =>
Monad[F].map(that.run)(list1 ++ _)
})
def run = fa
}
Once we are done with modifying, we can get the resulting object by calling the run method on the ListT object. If you want, you can also add other list specific operations like in scalaz. This should be pretty straight forward. For example a :: could look as follows:
def ::(x: A) = ListT(Monad[F].map(fa)(x :: _))
Usage:
scala> ListT(Option(List(1,2,3)))
res6: ListT[Option,Int] = ListT(Some(List(1, 2, 3)))
scala> res6.map(_+45)
res7: ListT[Option,Int] = ListT(Some(List(46, 47, 48)))
scala> 13 :: res7
res8: ListT[Option,Int] = ListT(Some(List(13, 46, 47, 48)))
scala> res8.run
res10: Option[List[Int]] = Some(List(13, 46, 47, 48))
I think scalaz.ListT is incorrect in scalaz 7.0.x and 7.1.x.
https://github.com/scalaz/scalaz/issues/921
6.x version is correct. but it is same as StreamT.
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]