Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix type inference error in this fold example?

Suppose I am writing:

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 it 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 it around but it does not look particularly 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 would you suggest solving this type problem ?

like image 785
Michael Avatar asked Apr 12 '15 08:04

Michael


Video Answer


2 Answers

As you see fold infers return type from the zero/fallback value provided as first arg. There it is Error as it resolve the most specific type of the value.

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

opt.fold[Status](err)(x => Ok(x))
opt.fold(err: Status)(x => Ok(x))
like image 170
cchantep Avatar answered Sep 19 '22 13:09

cchantep


fold signature looks like:

final def fold[B](ifEmpty: ⇒ B)(f: (A) ⇒ B): B

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

You can fix it being explicit with the type as follows:

scala> def foo(opt: Option[Int]): Status = opt.fold[Status](Error1)(x => Ok(x))
foo: (opt: Option[Int])Status
like image 35
moliware Avatar answered Sep 20 '22 13:09

moliware