Difference between parSequence and starting fibers manually - scala

I have got two program's implementatnion
def program_valid: IO[Unit] = for {
interpreter <- Interpreter[IO]
fib1 <- display(interpreter).start
fib2 <- read(interpreter).start
_ <- fib1.join
_ <- fib2.join
} yield ()
def program_invalid: IO[Unit] = for {
interpreter <- Interpreter[IO]
_ <- (read(interpreter), display(interpreter)).parSequence
} yield ()
First one works perfectly well which means both fibers keep running (dispaly and read). Unfortunately second implementatnion works different. It looks like only the display fiber would run. Why it goes like that? What is the difference here?

parSequence is for collections (well actually for types with an instance of Traverse), not sure how it even compiles; well I mean there is probably a Traverse instance for Tuple2 but it definitively doesn't do what you want.
You may use:
_ <- (read(interpreter), display(interpreter)).parTupled.void
// Or
_ <- IO.both(read(interpreter), display(interpreter)).void
// Or
_ <- read(interpreter).both(display(interpreter)).void
// Or
_ <- List(read(interpreter), display(interpreter)).parSequence_

Related

Is there any difference between calls in main thread and unsafeRunSync?

Is there any difference between just
call1()
call2()
and
val res = for {
_ <- IO(call1())
_ <- IO(call2())
...
} yield somevalue
res.unsafeRunSync
What variant is safer (and is there any difference at all)?

List to multiple anonymous/underscore parameters in for-comprehension

I'm kind of new to Scala/functional so I'm not yet able to use technical language.
I'm experiencing problems with a for-comprehension
val queries =
for {
_ <- createBanco
_ <- createBancoMedio
bankInsertions <- Update[Banco](insertStr).updateMany(NonEmptyList.fromList(createBankList(1, maxBanks)).get)
mediumInsertions <- Update[BancoMedio](mediumInsert).updateMany(NonEmptyList.fromList(mediumList).get)
bankCount <- BancoStatements.getCount().unique
bankGetIds <- BancoStatements.getIds(0, maxBanks).to[List]
bankSome <- BancoStatements.getSome(halfBanks).to[List]
} yield (bankCount, bankGetIds, bankSome)
//Execute database queries, saves them on tuple
val transactionResults : (Int, List[String], List[Banco]) =
queries.transact(h2Transactor).unsafeRunSync()
I'm trying to refactor the _ <- createBanco & _ <- createBancoMedio, which are both a ConnectionIO[Int] object.
Id like to convert those to a single List(createBanco, createBancoMedio) and then execute transact.
However, i'd be altering the return type of the for-comprehension by doing that. I'd like to know if there is any way on doing that without affecting the for output value
Basically, treat the list as if I was writing multiple anonymous parameters manually.
You can use .sequence to turn a List[G[A]] into a G[List[A]] if G has an Applicative instance, which ConnectionIO does:
val queries =
for {
_ <- List(createBanco, createBancoMedio).sequence
...
Just solved it, did another for comprehension for the List
val createList = for {
m <- createBancoMedio
b <- createBanco
} yield List(b, m)
val queries =
for {
_ <- createList ....
This way i had a ConnectionIO[List[Int]]

How to improve the code of a method which uses 'Free monad'?

I'm trying some code which inspects this slides about Free Monad in Scala, and made a small project with some slightly changed code.
The project is here: https://github.com/freewind/free-the-monads
Everything seems good at first, the code is clean and beautiful:
def insertAndGet() = for {
_ <- Script.insert("name", "Freewind")
value <- Script.get("name")
} yield value
def insertAndDelete() = for {
_ <- Script.insert("name", "Freewind")
_ <- Script.delete("name")
value <- Script.get("name")
} yield value
def insertAndUpdateAndDelete() = for {
_ <- Script.insert("name", "Freewind1")
oriValue <- Script.update("name", "Freewind2")
_ <- Script.delete("name")
finalValue <- Script.get("name")
} yield (oriValue, finalValue)
But when my logic is complex, e.g. there is some Script[Option[_]], and I need to check the option value to decide to do something, I can't use the for-comprehension any more, the code is like:
private def isLongName(name: String): Script[Boolean] = for {
size <- Script.getLongNameConfig
} yield size.exists(name.length > _)
def upcaseLongName(key: String): Script[Option[String]] = {
Script.get(key) flatMap {
case Some(n) => for {
isLong <- isLongName(n)
} yield isLong match {
case true => Some(n.toUpperCase)
case false => Some(n)
}
case _ => Script.pure(None)
}
}
I found the Free Monad approach is really interesting and cool, but I'm not familiar with scalaz, and just beginning to learn Monad things, not sure how to improve it.
Is there any way to make it better?
PS: You can just clone the project https://github.com/freewind/free-the-monads and try it yourself
This is a good use case for the OptionT monad transformer:
import scalaz.OptionT, scalaz.syntax.monad._
def upcaseLongName(key: String): OptionT[Script, String] = for {
n <- OptionT.optionT(Script.get(key))
isLong <- isLongName(n).liftM[OptionT]
} yield if (isLong) n.toUpperCase else n
Here OptionT.optionT converts a Script[Option[String]] into an OptionT[Script, String], and .liftM[OptionT] raises a Script[Boolean] into the same monad.
Now instead of this:
println(upcaseLongName("name1").runWith(interpreter))
You'd write this:
println(upcaseLongName("name1").run.runWith(interpreter))
You could also have upcaseLongName return an Script[Option[String]] directly by calling run there, but if there's any chance you'll need to be composing it with other option-y script-y things it's probably best to have it return OptionT[Script, String].

Why are these scalacheck recursive generators not equivalent?

While trying to learn the ScalaCheck tool, I wrote two versions of a Map generator (I know there is one of these built in, but this was an exercise).
It seems that genMap0 and genMap00 should be equivalent, and genMap00 is bit cleaner, but in fact genMap0 works, but genMap00 fails miserably.
The yield is adorned with a println that can be turned on to see what happening (just edit the speak method), but even with this information I cannot say I really understand why the difference. This makes me think that another generator I try to write may also be flawed.
Can someone give a nice explanation of what is different between genMap0 and genMap00?
import org.scalacheck._
import Arbitrary._
import Gen._
import Prop._
def speak(message: String): Unit = if (false) println(message)
lazy val genMap0: Gen[Map[Int, Int]] = for {
k <- arbitrary[Int]
v <- arbitrary[Int]
b <- arbitrary[Boolean]
m <- if (b) value(Map.empty[Int, Int]) else genMap0
} yield if (b) {
speak("false"); m
} else {
speak("true"); m.updated(k, v)
}
lazy val genMap00: Gen[Map[Int, Int]] = for {
k <- arbitrary[Int]
v <- arbitrary[Int]
m <- oneOf(Map.empty[Int, Int], genMap00)
} yield if (m.isEmpty) {
speak("empty:" + m); m
} else {
speak("not empty:" + m); m.updated(k, v)
}
val n = 5
for (i <- 1 to n; m <- genMap0.sample) println(m)
println("--------------")
for (i <- 1 to n; m <- genMap00.sample) println(m)
This is the output (genMap00 always generates the empty map):
scala -cp scalacheck_2.10-1.10.1.jar
...
// Exiting paste mode, now interpreting.
Map()
Map(1 -> 1, 1530546613 -> -1889740266, -187647534 -> 0)
Map()
Map(-1 -> 2039603804)
Map(646468221 -> 1)
--------------
Map()
Map()
Map()
Map()
Map()
The problem the recursive generation always starts with an empty map, so gen00 always ends up with a generator that produces an empty map. The problem is the empty condition is also being used to detect termination.
This is fixed by gen000:
lazy val genMap000: Gen[Map[Int, Int]] = for {
k <- arbitrary[Int]
v <- arbitrary[Int]
m <- oneOf(None, genMap000.map(g => Some(g)))
} yield (for (x <- m) yield x.updated(k, v)).getOrElse(Map())
This uses an intermediate Option[Map], with the None state indicating termination.
Using the explicit Boolean generator appears to be cleaner.

Future[Option[Boolean]] in a for comprehension.. Simple right?

Suppose I have:
val res:Future[Option[Boolean]] = Future(Some(true))
and I can do:
res.map(opt => opt.map(r => print(!r)))
I guess the for comprehension for this would be:
for {
opt <- res
r <- opt
} yield (print(!r))
but this does not work! I get an error ie:
error: type mismatch;
found : Option[Unit]
required: scala.concurrent.Future[?]
r <- opt
How do I use a Future[Option[Boolean]] in a for comprehension to extract or convert the Boolean?
Note: this is a simplification of the problem I have at the moment with many Future[Option[Boolean]] variables that I would like to use together in a for comprehension.
A for-comprehension really makes this look like it should all work, doesn't it? But let's think about what you're asking for.
First, note that for un-nests:
for {xs <- List(List(5)); x <- xs} yield x
produces
List(5)
Now, without even getting into the type signatures or desugaring, we can think about replacing List with some arbitrary type T, and we'll call the contained type A:
for { xs <- T(T(a: A)); x <- xs } yield x
and we should get a
T[A]
back (presumably the one we put in, but the types don't actually promise us that).
Okay, but what about
for { xs <- T(U(a: A)); x <- xs } yield x
? This is strictly more general than the case where the two things have the same nesting. Well, if T and U both have a common supertype S, then we can just view the whole thing as S(S(a: A)), so we'll at least get an S back. But what about in the general case?
The bottom line is that it depends. For example, let's consider the case where T=Future, U=Option. We have the following possibilities:
Success(Some(a))
Success(None)
Failure(t: Throwable)
Now, can we come up with any coherent policy for unwrapping? If we unwrap into a Future, then what A do you use for the Success(None) case? You don't have one available to return. Likewise, if you try to vanquish the outer Future, how do you know, without explicitly stating it somehow to the compiler, that Failure should be mapped to None (if indeed it should--maybe it should go to a default!).
So the bottom line is that you just can't do this correctly in general without specifying what is supposed to happen for every pair T[U[_]]. (I encourage the interested reader to peruse tutorials on monads and monad transformers.)
There is a way out, though: if you can explicitly turn your U into a T, or your T into your U, you can take advantage of the unwrapping capability. It's pretty easy to turn an Option into a Future , so the easiest solution is
for { opt <- res; r <- Future(opt.get) } yield r
(where just let the exception get thrown on none.get). Alternatively, you can turn the Future into an Option with the slightly ugly
for { opt <- res.value.flatMap(_.toOption); r <- opt } yield r
Equivalent code for
for {
opt <- res
r <- opt
} yield (print(!r))
is not
res.map(opt => opt.map(r => print(!r)))
but
res.flatMap(opt => opt.map(r => print(!r)))
And it makes no sense in this case.
For the chain of maps you could use nested for-comprehensions
for { opt <- res }
for { r <- opt }
print(!r)
But map looks better.
Well, for comprehensions are deceiving in the way they look. Your for-comprehension expands to:
res.flatMap(opt => opt.map(r => print(!r))
Which is obviously wrong as flatMap expects a return type of Future[T] and you are providing Option[Unit]
Though sometimes, for code tidiness you would want to have a single for loop with many such expressions. In those cases you could:
scala> implicit def toFuture[T](t: => T):Future[T] = {
| val p = Promise[T]()
| p.tryComplete(Try(t))
| p.future
| }
scala> for {
| opt <- res
| r <- opt
| } yield {print(!r)}
false
The above produces:
res.flatMap[Option[Unit]](((opt: Option[Boolean]) =>
toFuture[Option[Unit]](opt.map[Unit](((r: Boolean) => print(!r))))))
Edit: Though you need to take all the pain if you are using yield. If you do not wish to use for comprehension as an expression, then you can do as you desired:
scala> val i = Future(Some(true))
i: scala.concurrent.Future[Some[Boolean]] = scala.concurrent.impl.Promise$DefaultPromise#6b24a494
scala> val j = Option(1)
j: Option[Int] = Some(1)
scala> val k = Right(1).right
k: scala.util.Either.RightProjection[Nothing,Int] = RightProjection(Right(1))
scala>
| for{
| x <- i
| y <- j
| z <- k
| }{
| println(i,j,k)
| }
(scala.concurrent.impl.Promise$DefaultPromise#6b24a494,Some(1),RightProjection(Right(1)))
This way no implicit is required. As compiler uses foreach at every junction. -Xprint:typer gives:
i.foreach[Unit](((x: Option[Boolean]) =>
j.foreach[Any](((y: Int) =>
k.foreach[Unit](((z: Int) => println(scala.this.Tuple3.apply[scala.concurrent.Future[Option[Boolean]], Option[Int], Either.RightProjection[Nothing,Int]](i, j, k))))))))
}