Reputation: 34099
I have the following code, that does not compile:
object PcpProtocol {
private type PcpKV = String
private val findPublicKey: List[PcpKV] => Either[String, Map[String, String]] = kv =>
kv
.filter(_.contains("PUBLIC:"))
.foldLeft(Left("Can not find the public key from SAP.")) { (_, a) =>
a.split(":").toList match {
case List(key, value) => Right(Map(key -> value))
}
}
}
The compiler complains:
type mismatch;
[error] found : scala.util.Right[Nothing,scala.collection.immutable.Map[String,String]]
[error] required: scala.util.Left[String,Nothing]
[error] case List(key, value) => Right(Map(key -> value))
What am I doing wrong?
Upvotes: 2
Views: 744
Reputation: 22625
The compiler can't infer type Either[String, Map[String, String]]
correctly because it narrows it to Left[String]
.
You can add type explicitily:
.foldLeft(Left("Can not find the public key from SAP."): Either[String, Map[String, String]]) { (_, a) =>
or:
.foldLeft[Either[String, Map[String, String]]](Left("Can not find the public key from SAP.")) { (_, a) =>
If you use cats in your project you could also use:
"Can not find the public key from SAP.".asLeft[Map[String, String]]
It often a good idea to create type alias for either, like:
type ErrorOr[T] = Either[String, T]
which could give you a little bit more readability:
.foldLeft[ErrorOr[Map[String, String]]]
Upvotes: 4
Reputation: 20534
You can help compiler by specifying type explicitly.
private val findPublicKey: List[PcpKV] => Either[String, Map[String, String]] = kv =>
kv
.filter(_.contains("PUBLIC:"))
.foldLeft[Either[String, Map[String, String]]](Left("Can not find the public key from SAP.")) { (_, a) =>
a.split(":").toList match {
case List(key, value) => Right(Map(key -> value))
}
}
Upvotes: 4