Suppose I need to convert Option[Int] to Either[String, Int] in Scala. I'd like to do it like this:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number")) {x => Right(x)}
Unfortunately the code above doesn't compile and I need to add type Either[String, Int] explicitly:
ox.fold(Left("No number"): Either[String, Int]) { x => Right(x) }
Is it possible to convert Option to Either this way without adding the type ?
How would you suggest convert Option to Either ?
No, if you do it this way, you can't leave out the type.
The type of Left("No number") is inferred to be Either[String, Nothing]. From just Left("No number") the compiler can't know that you want the second type of the Either to be Int, and type inference doesn't go so far that the compiler will look at the whole method and decide it should be Either[String, Int].
You could do this in a number of different ways. For example with pattern matching:
def foo(ox: Option[Int]): Either[String, Int] = ox match {
case Some(x) => Right(x)
case None => Left("No number")
}
Or with an if expression:
def foo(ox: Option[Int]): Either[String, Int] =
if (ox.isDefined) Right(ox.get) else Left("No number")
Or with Either.cond:
def foo(ox: Option[Int]): Either[String, Int] =
Either.cond(ox.isDefined, ox.get, "No number")
I am not sure which version of Scala you were using at the time. Currently, with Scala 2.12.6 there's no compilation problems with your code like this:
def foo(ox: Option[Int]): Either[String, Int] =
ox.toRight("No number")
One other point I'd like to make is that folding (while it's my preferred method of collapsing just about anything that has a fold method on it) quite often requires help with type parameters. There's two ways the compiler can type check an expression, either it can infer the type parameters or it can simply find them explicitly defined.
In your example, if you're trying to fold an option like so:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number") : Either[String, Int])(x => Right(x))
You're explicitly providing type information about the first argument, which in turn can be then used to infer the type parameter of fold. You're aiding the type inference mechanism.
On the other hand, you could simply just explicitly provide the type parameter for fold like so:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold[Either[String, Int]](Left("No number"))(x => Right(x))
Now your actual (value-level) arguments are not littered with superfluous type information, and there's no type inference going on when the compiler looks at it, it can tell right away what fold's type parameter is, as it's been explicitly provided. Use the square brackets to specify the type parameter explicitly.
One more point, regarding x => Right(x) here you're practically creating a new function literal that does nothing other than pass x into the apply method of the Right case class's companion object. You already have a function of the appropriate shape available. It takes x and returns a Right(x). It is the apply method. You can refer to it (pass it) directly.
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold[Either[String, Int]](Left("No number"))(Right.apply)
The reason why type annotation is necessary is because of the way type inference works in Scala 2 for multiple parameter lists where
parameter list are considered one at a time, and
constraints accumulated in first parameter lists are applied to the next parameter list.
Consider signature of Option#fold
def fold[B](ifEmpty: => B)(f: A => B): B
where we see type parameter B and two parameter lists. Now type of argument provided to the first parameter list is Left[String,Nothing] because
scala> Left("No number")
val res0: scala.util.Left[String,Nothing] = Left(No number)
which means type parameter B is inferred to be Left[String,Nothing], which in turn constrains the expected type of the argument provided to the second parameter list to be a function of Left return type
A => Left[String,Nothing]
however we are providing a function of Right return type, therefore it errors with type mismatch
Welcome to Scala 2.13.3 (OpenJDK 64-Bit Server VM, Java 1.8.0_252).
Type in expressions for evaluation. Or try :help.
scala> def foo(ox: Option[Int]): Either[String, Int] =
| ox.fold(Left("No number")) {x => Right(x)}
ox.fold(Left("No number")) {x => Right(x)}
^
On line 2: error: type mismatch;
found : scala.util.Right[Nothing,Int]
required: scala.util.Left[String,Nothing]
Note that Scala 3 (Dotty) brings improvements to type inference so your snippet would work out of the box without having to provide explicit type annotation
Starting dotty REPL...
scala> def foo(ox: Option[Int]): Either[String, Int] =
| ox.fold(Left("No number")) {x => Right(x)}
|
def foo(ox: Option[Int]): Either[String, Int]
Related
Experimenting with Scala 3's metaprogramming capabilities, I found this issue with inline matching that I'm not able to satisfy myself with an explanation for.
Given a transparent inline method eitherTest which takes an inlined Either[String, Int] and then returns either the String or the Int directly using an inline match expression, things work perfectly fine if the input to eitherTest is explicitly typed to a Left or a Right. However, the compiler appears to be unable to reduce the match expression if the input is explicitly typed to the supertype of Either. What makes this more curious is that the argument to eitherTest is itself typed as Either.
Is this a compiler bug? Is this expected behavior? I'm struggling to understand why the compiler would not be able to resolve this.
Scastie link: https://scastie.scala-lang.org/CThqajauRVeJvxvW0uYy4w
Code:
#main def hello: Unit =
workingTest
failingTest
def workingTest: Unit =
val l: Left[String, Int] = Left("hello")
val r: Right[String, Int] = Right(22)
val tl: String = eitherTest(l)
val tr: Int = eitherTest(r)
println(s"$tl :: $tr")
def failingTest: Unit =
val l: Either[String, Int] = Left("hello")
val r: Either[String, Int] = Right(22)
val tl: String = eitherTest(l)
val tr: Int = eitherTest(r)
println(s"$tl :: $tr")
transparent inline def eitherTest(inline v: Either[String, Int]): Any =
inline v match
case Right(a) => a
case Left(b) => b
Error:
cannot reduce inline match with
scrutinee: l : (l : Either[String, Int])
patterns : case Right.unapply[String, Int](a # _):Right[String, Int]
case Left.unapply[String, Int](b # _):Left[String, Int]
val l: Either[String, Int] = Left("hello")
val r: Either[String, Int] = Right(22)
This explicitly discards type information, leaving the compiler unable to infer what it needs. I believe the transparent relies on type knowledge of passed arguments, rather than "dark type magic" around statically defined values. If you erase the type of the passed arguments, then it is fair to fail right?
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)]
Why does this code not type check?
def foo: Either[String, List[Int]] = {
val x = null: Either[String, String]
x match {
case l # Left(_) => l
case Right(_) => Right(List(3))
}
}
Specifically, why can't/doesn't the compiler reify the type of Left[A,X] and Either[A,B]?
This happened in scala 2.8.2 and scala 2.9.2
There is a genuine conflict here:
Left[String, String] <: Either[String, List[Int]]
is not true. Left is typed on both left and right parameters, and even though there is no actual difference between the two (so casting would be safe), this is not what you have told the compiler. So, of course, it will complain.
There are other weaknesses in type inference in pattern matching, but this is not one of them.
Edit: one can imagine an alternate singly-parameterized implementation of Left in which
Left[String] <: Either[String, Nothing] <: Either[String, List[Int]]
which would throw away type information. Methods like swap would be tricker to use, but it would allow the pattern given by the OP. However, the type-preserving form was used in the standard implementation in Scala.
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)]
I answered a question about a map of functions in Defining a Map from String to Function in Scala which led to a Function1[_, String] which I believe is correct as far as the typing question but possibly useless because I don't know how to invoke such a function:
scala> def f(x: Int) = x.toString
f: (x: Int)java.lang.String
scala> f(8)
res0: java.lang.String = 8
scala> val g: Function1[_, String] = f _
g: Function1[_, String] = <function1>
scala> g(8)
<console>:8: error: type mismatch;
found : Int(8)
required: _$1 where type _$1
g(8)
^
scala> val h: Function1[Int, String] = g
<console>:7: error: type mismatch;
found : (_$1) => String where type _$1
required: (Int) => String
val h: Function1[Int, String] = g
Is there any way to use g?
scala> g.asInstanceOf[Any => String](5)
res3: String = 5
It will work because all functions erase to the same thing: Function1[AnyRef, AnyRef]. When you specify it as Any, then passing an AnyVal will auto-box it on call (and it will be auto-unboxed at the method).
However, you do have to pass the correct parameter type. Or else...
scala> g.asInstanceOf[Any => String](true)
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Integer
I would say that it's like if you've cast an object of type String as Any, if you want to use a method defined in String you have to cast it back as a String.
You cast the function as a function that takes an argument of an existential type (which is what _ in a type context means), so you can't use it as a function that takes an Int. To use it as a function that takes an Int you have to cast it back.
The same problem exists when pattern matching with collections, or other generic classes:
def firstLength(collection: Any): Int ={
collection match {
// this is how you would have liked to write it
// case list: List[String] => list.head.length
// case map: Map[String, String] => map.values.head.length
// but this is how you have to write it because of type erasure
case list: List[_] => list.asInstanceOf[List[String]].head.length
case map: Map[_, _] => map.asInstanceOf[Map[String, String]].values.head.length
}
}
The type information isn't there, so you can't match on List[String], instead you have to match on the existential type List[_] (might be wrong on how you say that, it's not the generic type that is existential, I think) and then cast. This is more or less exactly the problem you have, the type you're after has been erased, and there's no way to get it back (unless you can use the same trick with ClassManifest that can be used to get around type erasure in cases like the one above [but not actually the case above, because it's a bit sloppy]).