Type resolution with flatMap - scala

why do i need to add the type annotation at the first line?
c.get[List[String]]("primary-group") is Decoder.Result[List[String]] after flatMap it should keep the top type and be Decoder.Result[String] but it changes to Either[DecodingFailure, String]. Why? Is the problem that it is dependent type?
case class JWTPayload(primaryGroup: Group, groupMember: List[Group], name: String, pid: String)
implicit val jwtPayloadDecoder: Decoder[JWTPayload] = Decoder.instance(c =>
(
c.get[List[String]]("primary-group").flatMap(l => if(l.size == 1) l.head.asRight else DecodingFailure("", c.history).asLeft) : Decoder.Result[String],
c.get[List[String]]("group-member"),
c.get[String]("name"),
c.get[String]("pid")
).map4(
JWTPayload
)
)
Without : Decoder.Result[String I get
Error:(43, 7) value map4 is not a member of (scala.util.Either[io.circe.DecodingFailure,String], io.circe.Decoder.Result[List[String]], io.circe.Decoder.Result[String], io.circe.Decoder.Result[String])
possible cause: maybe a semicolon is missing before `value map4'?
).map4(
Thanks

This is not a full answer but I hope it will provide some insights. The crucial part here is how map4 is implemented. As of cats 0.9 it is done via cats.syntax.TupleCartesianSyntax trait and its implicit catsSyntaxTuple4Cartesian which wraps a 4-tuple into a cats.syntax.Tuple4CartesianOps class (in cats 1.0 "cartesian" was changed to "semigroupal"). This code is auto-generated for all tuples up to 22 by Boilerplate.scala. The auto-generated code looks something like this:
implicit def catsSyntaxTuple4Cartesian[F[_], A0, A1, A2, A3](t4: Tuple4[F[A0], F[A1], F[A2], F[A3]]): Tuple4CartesianOps[F, A0, A1, A2, A3] = new Tuple4CartesianOps(t4)
private[syntax] final class Tuple4CartesianOps[F[_], A0, A1, A2, A3](t4: Tuple4[F[A0], F[A1], F[A2], F[A3]]) {
def map4[Z](f: (A0, A1, A2, A3) => Z)(implicit functor: Functor[F], cartesian: Cartesian[F]): F[Z] = Cartesian.map4(t4._1, t4._2, t4._3, t4._4)(f)
def contramap4[Z](f: Z => (A0, A1, A2, A3))(implicit contravariant: Contravariant[F], cartesian: Cartesian[F]): F[Z] = Cartesian.contramap4(t4._1, t4._2, t4._3, t4._4)(f)
def imap4[Z](f: (A0, A1, A2, A3) => Z)(g: Z => (A0, A1, A2, A3))(implicit invariant: Invariant[F], cartesian: Cartesian[F]): F[Z] = Cartesian.imap4(t4._1, t4._2, t4._3, t4._4)(f)(g)
def apWith[Z](f: F[(A0, A1, A2, A3) => Z])(implicit apply: Apply[F]): F[Z] = apply.ap4(f)(t4._1, t4._2, t4._3, t4._4)
}
Note the F[_] (functor) type parameter. Effectively this code adds map4 method to any 4-tuple where each inner type is the same functor over some types.
So assuming you did import cats.implicits._, after (partial) implicits resolution your code is actually something like this:
cats.implicits.catsSyntaxTuple4Cartesian[Decoder.Result, String, List[String], String, String](
c.get[List[String]]("primary-group").flatMap(l => if (l.size == 1) l.head.asRight else DecodingFailure("", c.history).asLeft): Decoder.Result[String],
c.get[List[String]]("group-member"),
c.get[String]("name"),
c.get[String]("pid")
).map4[JWTPayload](
JWTPayload
)
When you don't specify Decoder.Result[String], Scala compiler is not smart enough to get that it should split Either[DecodingFailure, String] into a functor type Either[DecodingFailure, _] and String and then
there will be matching Functor and Cartesian implicit objects (actually provided by the cats.implicits object via cats.instances.AllInstances and cats.instances.EitherInstances traits)
it would match the functor type used for other 3 fields in the tuple (i.e. Decoder.Result[_]).
So I think this behavior is a result of a combination of the fact that map4 is added to 4-tuple via an implicit Ops-class and the fact that the underlying type is Either which is 2-places generic type rather than a simple Functor.

Related

What's the relationship between PartialFunction and Function1

I'm learning Scala, and find from scala doc the definition of PartialFunction and Function1, as shown below:
trait PartialFunction[-A, +B] extends (A) ⇒ B
trait Function1[-T1, +R] extends AnyRef
Q1) My 1st question is: what's the type of (A) => B?
And, I know we can turn the PartialFunction to be a normal function by the lift method.
But Q2) what's the relationship between ParitialFunction and Function1?
It seems if some function parameter is of type Function1, we can pass a matching PartitionFunction to it, as shown below:
scala> val process = (f: Function1[String, Int]) => f("1024")
process: (String => Int) => Int = <function1>
scala> val pattern = "([0-9]+)".r
pattern: scala.util.matching.Regex = ([0-9]+)
scala> val str2int: PartialFunction[String, Int] = {
| case pattern(num) => num.toInt
| }
str2int: PartialFunction[String,Int] = <function1>
scala> accept(str2int)
res67: Int = 1024
Thanks!
A ⇒ B is syntax sugar for Function1[A, B]. Similarly, (A1, A2) ⇒ R is actually Function2[A1, A2, R], etc. all the way to 22 (completely arbitrary limit). The definition of PartialFunction is thus
trait PartialFunction[-A, +B] extends Function1[A, B]
Since a PartialFunction[A, B] is also a Function1[A, B], you can pass it into something that wants an A ⇒ B. The only reason we use ⇒ over FunctionN is aesthetic: it looks nicer. Indeed, since ⇒ isn't really a type name, we can't say something like:
type ApIntInt[T[_, _]] = T[Int, Int]
// ApIntInt[⇒] // Error: ⇒ is not a type and was not expected here
ApIntInt[Function1] // Fine: Function1 is a type, it has the right kind, so it works.
// ApIntInt[Function1] = Function1[Int, Int] = Int ⇒ Int
Since you're a beginner, you won't see this kind of stuff (higher kinds) for a long time yet, but it is there, and you may well hit it someday.
When you use a PartialFunction as a Function1, if you pass a value at which it is not defined, it (probably) throws an exception, which is usually a MatchError (but doesn't have to be). By contrast, if you call pf.lift, that creates a Function[In, Option[Out]], which returns Some(result) if the PartialFunction is defined at a point, and returns None if it isn't, per the Scaladoc.
Ex:
lazy val factorial: PartialFunction[Int, Int] = {
case num if num > 1 => num * factorial(num - 1)
case 1 => 1
}
assert(!factorial.isDefinedAt(0))
factorial.apply(0) // Using a PF as a Function1 on an undefined point breaks (here with MatchError)
factorial.lift.apply(0) // This just returns None, because it checks isDefinedAt first

How to check if types are Tuple in compile time

I have the following case class:
case class MyClass[A,B](a:A, b:B)
I want to add a function like unzip to MyClass so if A and B are Tuple types then I want to extract them like the following:
val item = MyClass[(Int,String), (Int,String)]((2,"two"), (3,"three"))
val item_left = MyClass(item.a._1, item.b._1)
val item_right = MyClass(item.a._2, item.b._2)
How should I do that and check the type for tuple in compile time? I don't want to define it in the companion object and I want it to be a function in MyClass. I know that I can define an implicit function but is it the only way?
You can use the <:< type class to prove that A and B are sub-types of Tuple2, so that you can decompose them. That is, we can write an unzip method to have the some free type parameters that would be the decomposed ordinate types (call them A1, A2, B1, and B2). Then, we require evidence that A <:< (A1, A2) and B <:< (B1, B2). If the sub-typing relationship is true, the compiler will find instances of these type classes, which we can use to finalize the conversion. That is, A <:< (A1, A2) extends the function A => (A1, A2).
case class MyClass[A, B](a: A, b: B) {
def unzip[A1, A2, B1, B2](implicit
ev1: A <:< (A1, A2),
ev2: B <:< (B1, B2)
): (MyClass[A1, A2], MyClass[B1, B2]) = {
val (a1, a2) = ev1(a)
val (b1, b2) = ev2(b)
(MyClass(a1, a2), MyClass(b1, b2))
}
}
In action:
scala> MyClass((2, "two"), (3, "three")).unzip
res6: (MyClass[Int,String], MyClass[Int,String]) = (MyClass(2,two),MyClass(3,three))
For non-tuples:
scala> MyClass(1, 2).unzip
<console>:14: error: Cannot prove that Int <:< (A1, A2).
MyClass(1, 2).unzip
^
Michael's answer is excellent. You could also go a much simpler route if you're willing to require that A and B are sub-types of Product in the declaration of your case class:
case class MyClass[A <: Product, B <: Product](a:A, b:B) {
def item_left = (a.productIterator.toList(0), b.productIterator.toList(0))
// etc.
}
Now, you can write:
val x = MyClass((2,"two"), (3,"three"))
x.item_left
which results in:
(2,3)
of type (Any,Any).
I suggest this alternative only because it was unclear to me just how complex you're willing to be. I hope not to elicit any down votes ;)

Scala fold on a Sequence of a Tuple

I have the following method that I would like to apply fold operation on:
def rec(id: String, elems: Seq[(String, MyCase)]) = {
elems.fold(Seq.empty[(String, Seq[String])] { elem =>
....
}
}
What I do not get is the type of the elem is Nothing and I do not understand why it should be! Any clues?
You are missing the closing parentheses before the {, that's why your IDE, probably, thinks, the type is Nothing.
Also, you are, probably, looking for foldLeft, not fold (the first parameter of the latter must match the type of elements of the sequence).
Now the (simplified) signature of .foldLeft on Seq[A] is:
foldLeft[B](b: B)(f: (B,A) => B)
As you can see, it takes a function, that transforms a Tuple2 into the type of the first parameter. The first element of the tuple has the same type as the first param, the second element is the same type as the elements of the sequence.
In your example, B is Seq[(String, Seq[String])], and the sequence elements are (String, MyCase). The type of input to the function would therefore take a horribly looking tuple like this:
(Seq[(String, Seq[String])], (String, MyCase))
This is caused by you are not only want to fold, you also you want to map the tuple, see the fold method signature:
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
The input type and outtype must be same: A1,
so if want to map, you maybe want to try foldLeft:
def foldLeft[B](z: B)(op: (B, A) => B): B =
There is a generics for output type B without bounding to A.
also we can find the fold source code is calling:
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
use foldLeft maybe like:
elements.fold(Seq.empty[(String, Seq[String])])((a, b) => a ++ Seq((b._1, Seq[String]())))
2nd EDIT:
I'm an idiot. A fold must return the same value as the input type.
Replace all the below folds with foldLefts for example and it works.
You can't transform the data type in a standard fold.
It was compiling for me but I didn't notice the return type was useless.
The second parameter in a fold is a function:
(ResultType, SingleElement) => Result Type
In this case
(Seq[(String, Seq[String])], Seq[(String, MyCase)]) => Seq[(String, Seq[String])]
Your code only has one input on the second parameter so the compiler doesn't know what it is. So it should look something like:
elems.foldLeft(Seq.empty[(String, Seq[MyCase])] {(zeroSeq, nextElem) =>
//zeroSeq: Seq.empty[(String, Seq[MyCase]
//nextElem: (String, MyCase)
}
EDIT:
The following for example compiles:
case class MyCase(x: String)
val elems: Seq[(String, MyCase)] = Seq(("Hi", MyCase("B")))
elems.foldLeft(Seq.empty[(String, Seq[MyCase])]){(z, s) =>
z
}

How to apply implicit conversions between tuples?

I'm experimenting with currying/tupled as an alternative means to pass parameters to a function. In this journey, I'm facing some type difficulties.
I'd like to use implicit conversions to transform a tuple of parameters to the target type. This is what I expect:
Given (REPL example):
case class Cont(value:String) // a simplified container class
val paramTuple = (Cont("One"),Cont("2"))
def operate(s:String, i:Int): String = s+i // my target operation
implicit def contToString(c:Cont): String = c.value
implicit def contToInt(c:Cont): Int = c.value.toInt
//This works - obviously
operate(paramTuple._1, paramTuple._2)
>res4: String = One2
//This is what I want, but doesn't work
(operate _).tupled(params)
<console>:14: error: type mismatch;
found : (Cont, Cont)
required: (String, Int)
Q1: Why the tuple conversion doesn't work? (I'm expecting that an answer to that goes in the lines of: What's required is an implicit conversion between Tuple2[Cont,Cont] to Tuple2[String,Int] but that does not scale up)
Q2: What are my options to have such conversion working?
Keep in mind that I'd like to have a solution for an N-tuple, so defining a specific Tuple2 to Tuple2 is not really a good solution in this case. AFAIK, the magnet pattern works similarly, so I hope there's a way.
Q1: Why the tuple conversion doesn't work? (I'm expecting that an answer to that goes in the lines of: What's required is an implicit conversion between Tuple2[Cont,Cont] to Tuple2[String,Int] but that does not scale up)
Yes, you've got that right.
What are my options to have such conversion working?
You could do it this way:
implicit def liftImplicitTuple2[A, B, A1, B1](tuple: (A, B))
(implicit f1: A => A1, f2: B => B1): (A1, B1) =
(f1(tuple._1), f2(tuple._2))
implicit def liftImplicitTuple3[A, B, C, A1, B1, C1](tuple: (A, B, C))
(implicit f1: A => A1, f2: B => B1, f3: C => C1): (A1, B1, C1) =
(f1(tuple._1), f2(tuple._2), f3(tuple._3))
// etc for tuples as large as you need

What are type lambdas in Scala and what are their benefits?

Sometime I stumble into the semi-mysterious notation of
def f[T](..) = new T[({type l[A]=SomeType[A,..]})#l] {..}
in Scala blog posts, which give it a "we used that type-lambda trick" handwave.
While I have some intutition about this (we gain an anonymous type parameter A without having to pollute the definition with it?), I found no clear source describing what the type lambda trick is, and what are its benefits. Is it just syntactic sugar, or does it open some new dimensions?
Type lambdas are vital quite a bit of the time when you are working with higher-kinded types.
Consider a simple example of defining a monad for the right projection of Either[A, B]. The monad typeclass looks like this:
trait Monad[M[_]] {
def point[A](a: A): M[A]
def bind[A, B](m: M[A])(f: A => M[B]): M[B]
}
Now, Either is a type constructor of two arguments, but to implement Monad, you need to give it a type constructor of one argument. The solution to this is to use a type lambda:
class EitherMonad[A] extends Monad[({type λ[α] = Either[A, α]})#λ] {
def point[B](b: B): Either[A, B]
def bind[B, C](m: Either[A, B])(f: B => Either[A, C]): Either[A, C]
}
This is an example of currying in the type system - you have curried the type of Either, such that when you want to create an instance of EitherMonad, you have to specify one of the types; the other of course is supplied at the time you call point or bind.
The type lambda trick exploits the fact that an empty block in a type position creates an anonymous structural type. We then use the # syntax to get a type member.
In some cases, you may need more sophisticated type lambdas that are a pain to write out inline. Here's an example from my code from today:
// types X and E are defined in an enclosing scope
private[iteratee] class FG[F[_[_], _], G[_]] {
type FGA[A] = F[G, A]
type IterateeM[A] = IterateeT[X, E, FGA, A]
}
This class exists exclusively so that I can use a name like FG[F, G]#IterateeM to refer to the type of the IterateeT monad specialized to some transformer version of a second monad which is specialized to some third monad. When you start to stack, these kinds of constructs become very necessary. I never instantiate an FG, of course; it's just there as a hack to let me express what I want in the type system.
The benefits are exactly the same as those conferred by anonymous functions.
def inc(a: Int) = a + 1; List(1, 2, 3).map(inc)
List(1, 2, 3).map(a => a + 1)
An example usage, with Scalaz 7. We want to use a Functor that can map a function over the second element in a Tuple2.
type IntTuple[+A]=(Int, A)
Functor[IntTuple].map((1, 2))(a => a + 1)) // (1, 3)
Functor[({type l[a] = (Int, a)})#l].map((1, 2))(a => a + 1)) // (1, 3)
Scalaz provides some implicit conversions that can infer the type argument to Functor, so we often avoid writing these altogether. The previous line can be rewritten as:
(1, 2).map(a => a + 1) // (1, 3)
If you use IntelliJ, you can enable Settings, Code Style, Scala, Folding, Type Lambdas. This then hides the crufty parts of the syntax, and presents the more palatable:
Functor[[a]=(Int, a)].map((1, 2))(a => a + 1)) // (1, 3)
A future version of Scala might directly support such a syntax.
To put things in context: This answer was originally posted in another thread. You are seeing it here because the two threads have been merged. The question statement in the said thread was as follows:
How to resolve this type definition: Pure[({type ?[a]=(R, a)})#?] ?
What are the reasons of using such construction?
Snipped comes from scalaz library:
trait Pure[P[_]] {
def pure[A](a: => A): P[A]
}
object Pure {
import Scalaz._
//...
implicit def Tuple2Pure[R: Zero]: Pure[({type ?[a]=(R, a)})#?] = new Pure[({type ?[a]=(R, a)})#?] {
def pure[A](a: => A) = (Ø, a)
}
//...
}
Answer:
trait Pure[P[_]] {
def pure[A](a: => A): P[A]
}
The one underscore in the boxes after P implies that it is a type constructor takes one type and returns another type. Examples of type constructors with this kind: List, Option.
Give List an Int, a concrete type, and it gives you List[Int], another concrete type. Give List a String and it gives you List[String]. Etc.
So, List, Option can be considered to be type level functions of arity 1. Formally we say, they have a kind * -> *. The asterisk denotes a type.
Now Tuple2[_, _] is a type constructor with kind (*, *) -> * i.e. you need to give it two types to get a new type.
Since their signatures do not match, you cannot substitute Tuple2 for P. What you need to do is partially apply Tuple2 on one of its arguments, which will give us a type constructor with kind * -> *, and we can substitue it for P.
Unfortunately Scala has no special syntax for partial application of type constructors, and so we have to resort to the monstrosity called type lambdas. (What you have in your example.) They are called that because they are analogous to lambda expressions that exist at value level.
The following example might help:
// VALUE LEVEL
// foo has signature: (String, String) => String
scala> def foo(x: String, y: String): String = x + " " + y
foo: (x: String, y: String)String
// world wants a parameter of type String => String
scala> def world(f: String => String): String = f("world")
world: (f: String => String)String
// So we use a lambda expression that partially applies foo on one parameter
// to yield a value of type String => String
scala> world(x => foo("hello", x))
res0: String = hello world
// TYPE LEVEL
// Foo has a kind (*, *) -> *
scala> type Foo[A, B] = Map[A, B]
defined type alias Foo
// World wants a parameter of kind * -> *
scala> type World[M[_]] = M[Int]
defined type alias World
// So we use a lambda lambda that partially applies Foo on one parameter
// to yield a type of kind * -> *
scala> type X[A] = World[({ type M[A] = Foo[String, A] })#M]
defined type alias X
// Test the equality of two types. (If this compiles, it means they're equal.)
scala> implicitly[X[Int] =:= Foo[String, Int]]
res2: =:=[X[Int],Foo[String,Int]] = <function1>
Edit:
More value level and type level parallels.
// VALUE LEVEL
// Instead of a lambda, you can define a named function beforehand...
scala> val g: String => String = x => foo("hello", x)
g: String => String = <function1>
// ...and use it.
scala> world(g)
res3: String = hello world
// TYPE LEVEL
// Same applies at type level too.
scala> type G[A] = Foo[String, A]
defined type alias G
scala> implicitly[X =:= Foo[String, Int]]
res5: =:=[X,Foo[String,Int]] = <function1>
scala> type T = World[G]
defined type alias T
scala> implicitly[T =:= Foo[String, Int]]
res6: =:=[T,Foo[String,Int]] = <function1>
In the case you have presented, the type parameter R is local to function Tuple2Pure and so you cannot simply define type PartialTuple2[A] = Tuple2[R, A], because there is simply no place where you can put that synonym.
To deal with such a case, I use the following trick that makes use of type members. (Hopefully the example is self-explanatory.)
scala> type Partial2[F[_, _], A] = {
| type Get[B] = F[A, B]
| }
defined type alias Partial2
scala> implicit def Tuple2Pure[R]: Pure[Partial2[Tuple2, R]#Get] = sys.error("")
Tuple2Pure: [R]=> Pure[[B](R, B)]