How to fix type inference error in this bend example?

Suppose I write:

sealed trait Status object Error1 extends Status case class Ok(x: Int) extends Status def foo(opt: Option[Int]): Status = opt.fold(Error1)(x => Ok(x)) 

When I try in REPL, I get an error:

 scala> def foo(opt: Option[Int]): Status = opt.fold(Error1)(x => Ok(x)) <console>:11: error: type mismatch; found : Ok required: Error1.type def foo(opt: Option[Int]): Status = opt.fold(Error1)(x => Ok(x)) ^ 

I can work, but it does not look very elegant:

  // work around the type error above val error1: Status = Error1 def ok(x: Int): Status = Ok(x) def foo(opt: Option[Int]): Status = opt.fold(error1)(x => ok(x)) 

How do you propose to solve this type problem?

+6
source share
4 answers

As you can see, fold returns the return type from the null / fallback value provided as the first argument. There it is Error , because it resolves the most specific type of value.

You can annotate a crease in the following ways to indicate that you want Status .

 opt.fold[Status](err)(x => Ok(x)) opt.fold(err: Status)(x => Ok(x)) 
+6
source

The compiler reports that the type is Error1 because it is the type of the first parameter passed to reset.

In terms of answering a direct question, you can tell the compiler that this is Error1, but the corresponding type is Status, passing the type explicitly as Status

 sealed trait Status object Error1 extends Status case class Ok(x: Int) extends Status def foo(opt: Option[Int]): Status = opt.fold(Error1: Status)(x => Ok(x)) 

The foo function will then return as follows:

 scala> foo(Option(5)) res0: Status = Ok(5) 
+3
source
Signature

fold looks like this:

 final def fold[B](ifEmpty: β‡’ B)(f: (A) β‡’ B): B 

So this is a curry function with a type B parameter. Therefore, it first executes opt.fold(Error1) and indicates that B is Error1 . So, the second part (x => Ok(x)) should be (f: (A) => Error1) , and for this reason the compiler complains.

You can fix this explicitly with the type as follows:

 scala> def foo(opt: Option[Int]): Status = opt.fold[Status](Error1)(x => Ok(x)) foo: (opt: Option[Int])Status 
+3
source

In addition to the other answers, you can do this by using pattern matching:

 opt match { case None => Error1; case Some(x) => Ok(x) } 

since in this case the compiler uses type information from both branches and will look for a common type between Error1 and Ok(x) .

+2
source

All Articles