Mapping IO[Either[String, User]] into IO[User] in scala - scala

I have a data type that I want to map into another type in scala.
val x = IO[Either[String, User]] that I want to map into IO[User].
I'm thinking of a way different than pattern matching a more optimized one. because I'm only interested in the case of Right projection.
( just to clarify this result would be mapped as Ok for the Endpoint response)

Related

What is the intent behind `F[Something[F]]`?

I see a lot of F[Request[F]], F[Monitor[F]] and F[Something[F]] around. Although I understand the mechanics of how to handle this, I don't have an intuitive understanding of why some effect (F) should appear like this (both wrapping around Something and appearing inside that Something). Insights ?
A simple HTTP server can be represented with the following function:
Request => Response
However, we commonly need to perform an effectful operation such as retrieving data from database or call external service. Such cases we would define like this:
Request => F[Response]
http4s has own abstraction over Routes (Endpoints) called HttpRoutes[F] and it is type alias for Kleisli[OptionT[F, ?], Request, Response] as mentioned in the documentation.
As we know from cats documentation, Kleisli is just compositions of functions that return a monadic value like Option[A], Either[L, R], etc.
One of the most useful properties of functions is that they compose. That is, given a function A => B and a function B => C, we can combine them to create a new function A => C.
In this case http4s's Kleislei takes Request and returns F[Response], simply Request => F[Response]. F is an effect type.
With a bit of modification the above Request and Response types, we get the following:
type HttpRoutes[F] = Kleisli[OptionT[F, *], Request[F], Response[F]]
An HttpRoutes[F] is declared as a simple series of case statements. Each case statement attempts to match and optionally extract from an incoming Request[F]. The code associated with the first matching case is used to generate a F[Response[F]].
The simplest case statement matches all requests without extracting anything. The right hand side of the request must return a F[Response[F]].
We can see here simple demonstration of F[Response[F]]
scala> val getRoot = Request[IO](Method.GET, uri"/")
getRoot: org.http4s.Request[cats.effect.IO] = Request(method=GET, uri=/, headers=Headers())
scala> val io = service.orNotFound.run(getRoot)
io: cats.effect.IO[org.http4s.Response[cats.effect.IO]] = <function1>
Here cats.effect.IO[org.http4s.Response[cats.effect.IO]] is unresolved yet, this is aync result. It will be resolved in future at some point as simple Future/Promise. And we can enforce it to run:
scala> val response = io.unsafeRunSync
response: org.http4s.Response[cats.effect.IO] = Response(status=200, headers=Headers())
Kleisli
Http4s
Practical FP in Scala by Gabriel Volpe
F[_] is just an abstraction. It can be List or IO of something else with kind * -> *. The main idea that you can define common functions. A good example of this a Functor typeclass and the map function inside this class.
So in your code, you can say that you F is a functor (F[_]: Functor) and after it allows you to use a map function.

Using zipped collections to initialize a case class in scala

I have to generate a collection of object from some collections of primitive types. So I tried the following two methods and both work:
case class Gr (x:Int,y:Int, z:Int)
val x = List(1,2,4,2,5)
val y = Array(1,2,7,4,5)
val z = Seq(1,2,4,8,5)
(x,y,z).zipped.toList.map(a => Gr(a._1,a._2,a._3))
(x,y,z).zipped.map(Gr:(Int,Int,Int) => Gr)
So, which one is better and how does the second one actually work ? And is there a better way ?
The 1st one can be reduced to (x,y,z).zipped.toList.map(Gr.tupled) and 2nd can be reduced to (x,y,z).zipped.map(Gr), which seems to be shorter/clearer to me.
Recall that the argument to map() is, essentially, A => B, so instead of writing ds.map(d => Math.sqrt(d)), which is type Double => Double, we can simply write ds.map(Math.sqrt) because sqrt() is the correct type.
In this case, the Gr constructor is type (A,A,A) => B. The Scala compiler is able to take the output of zipped and match the constructor type, so the constructor can be used as the argument to map().

Ambiguous Implicit Values when using HMap

HMap seems to be the perfect data structure for my use case, however, I can't get it working:
case class Node[N](node: N)
class ImplVal[K, V]
implicit val iv1 = new ImplVal[Int, Node[Int]]
implicit val iv2 = new ImplVal[Int, Node[String]]
implicit val iv3 = new ImplVal[String, Node[Int]]
val hm = HMap[ImplVal](1 -> Node(1), 2 -> Node("two"), "three" -> Node(3))
My first question is whether it is possible to create those implicits vals automatically. For sure, for typical combinations I could create them manually, but I'm wondering if there is something more generic, less boilerplate way.
Next question is, how to get values out of the map:
val res1 = hm.get(1) // (1) ambiguous implicit values: both value iv2 [...] and value iv1 [...] match expected type ImplVal[Int,V]`
To me, Node[Int] (iv1) and Node[String] (iv2) look pretty different :) I thought, despite the JVM type erasure limitations, Scala could differentiate here. What am I missing? Do I have to use other implicit values to make the difference clear?
The explicit version works:
val res2 = hm.get[Int, Node[Int]](1) // (2) works
Of course, in this simple case, I could add the type information to the get call. But in the following case, where only the keys are known in advance, I don't know how to do it:
def get[T <: HList](keys: T): HList = // return associated values for keys
Is there any simple solution to this problem?
BTW, what documentation about Scala's type system (or Shapeless or in functional programming in general) could be recommended to understand the whole topic better as I have to admit, I'm lacking some background for this topic.
The type of the key determines the type of the value. You have Int keys corresponding to both Node[Int] and Node[String] values, hence the ambiguity. You might find this article helpful in explaining the general mechanism underlying this.

Scala Slick - Convert TableQuery[E] to Query[E] to chain operations

I'm trying to apply a series of optional filtering operations to a query by using a list of the operations and folding over the list.
val table = TableQuery[Fizz]
val filters = List(filter1(option1)_, filter2(option2)_, filter3(option3)_)
val filteredQuery = filters.foldLeft(table){(q, filter) => filter(q)}
The partially applied filter functions have a signature of
Query[Fizz, FizzRow, Seq] => Query[Fizz, FizzRow, Seq]
Basically, in each function, I am optionally applying the filtering if the filter parameter option* is present. However, the compiler does not like the fact that I am passing in a TableQuery to a function that takes Query, even though TableQuery is a subtype of Query. Is there a way to convert a TableQuery to Query? Or a better way to go about chaining filter functions on a query?
The compiler error in question is
type mismatch;
found :scala.slick.lifted.Query[generated.Tables.Farm,generated.Tables.FarmRow,Seq]
required: scala.slick.lifted.TableQuery[generated.Tables.Farm]
I can get it to compile by using table.drop(0) instead of table but obviously that seems like a poor workaround. I see that there's a to method on TableQuery that converts it to a Query but it also takes an implicit ctc: TypedCollectionTypeConstructor[D].
An example of one of the filterX functions listed above:
def filterCharacteristics(characteristics: Option[List[Int]])(table: Query[Farm,FarmRow,Seq]) = {
characteristics.map(chars =>
(for {
(fc, f) <- Farmcharacteristic.filter(_.characteristicId inSet chars) join table on (_.farmId === _.farmId)
} yield f)).getOrElse(table)
}
I think you can try another approach. Instead of using a fold, you can use a collect to get only the Some values.
Then you can apply a filter to each of the options you have:
val table = TableQuery[Fizz]
val filteredQueries = List(Some(option1), Some(option2), Some(option3)) collect {
case Some(option) => option
} map { currentOption =>
table.filter(currentOption)
}
// We need to get the last value or the TableQuery
val lastValue = filteredQueries reverse headOption
// Or we have Some(Query) or None, In case it is a None, we will use table
lastValue.getOrElse(table)

Converting a Scala Map to a List

I have a map that I need to map to a different type, and the result needs to be a List. I have two ways (seemingly) to accomplish what I want, since calling map on a map seems to always result in a map. Assuming I have some map that looks like:
val input = Map[String, List[Int]]("rk1" -> List(1,2,3), "rk2" -> List(4,5,6))
I can either do:
val output = input.map{ case(k,v) => (k.getBytes, v) } toList
Or:
val output = input.foldRight(List[Pair[Array[Byte], List[Int]]]()){ (el, res) =>
(el._1.getBytes, el._2) :: res
}
In the first example I convert the type, and then call toList. I assume the runtime is something like O(n*2) and the space required is n*2. In the second example, I convert the type and generate the list in one go. I assume the runtime is O(n) and the space required is n.
My question is, are these essentially identical or does the second conversion cut down on memory/time/etc? Additionally, where can I find information on storage and runtime costs of various scala conversions?
Thanks in advance.
My favorite way to do this kind of things is like this:
input.map { case (k,v) => (k.getBytes, v) }(collection.breakOut): List[(Array[Byte], List[Int])]
With this syntax, you are passing to map the builder it needs to reconstruct the resulting collection. (Actually, not a builder, but a builder factory. Read more about Scala's CanBuildFroms if you are interested.) collection.breakOut can exactly be used when you want to change from one collection type to another while doing a map, flatMap, etc. — the only bad part is that you have to use the full type annotation for it to be effective (here, I used a type ascription after the expression). Then, there's no intermediary collection being built, and the list is constructed while mapping.
Mapping over a view in the first example could cut down on the space requirement for a large map:
val output = input.view.map{ case(k,v) => (k.getBytes, v) } toList