How to avoid type inferencing Any when "converting" parametrized types

Hello,

I have the following code:

def conv[B](x : Throwable) : Either[List[Throwable], B] = Left( List(x) ) 

def doX[A,B,C](a: A, g: A => Try[A], f : A => Either[C,B] ) : Either[C,B] = {
  val t0 = g(a)
  val tt  = t0.fold( { x => conv(x) } , { x => f(x) } )
  tt
}

Compilation fails with:

type mismatch; found : scala.util.Either[Any,B] required: Either[C,B]

This is correct, however the signature:

def fold[U](fa: Throwable => U, fb: A => U): U

seems to indicate that one is allowed to convert a Throwable to a U, which in my case would be Either[List[Throwable], B]. The problem seems to be that the compiler sees List[Throwable] and C as two different types - resulting in an Any. Is it possible to ensure that the compiler binds C = List[Throwable] ? If so, what the scala (generic) way to do this?

TIA

Hello,

Do you mean something like:

def doX[A, B, C <: List[Throwable]]

 Best, Oliver

It’s not clear what your intent is, but as the question stands: the way you can ensure that C is List[Throwable] is to remove it as a type parameter and instantiate it as List[Throwable] everywhere.

def doX[A,B](a: A, g: A => Try[A], f : A => Either[List[Throwable],B]) : Either[List[Throwable],B] = {
  val t0 = g(a)
  val tt  = t0.fold( { x => conv(x) } , { x => f(x) } )
  tt
}

You can also simplify the body, by the way.

def doX[A,B](a: A, g: A => Try[A], f : A => Either[List[Throwable],B]) : Either[List[Throwable],B] =
  g(a).fold(conv, f)

@tpolecat and @curoli

Appreciate the help.

The intent is not to add the List[Throwable] explicitly. I would like to use any other conv function that can return an arbitrary type and have doX's C bind to that return type. I have gotten a little further on this:


    def doX3[A,B,C](c : Throwable => Either[C,B])(a: A, g: A => Try[A], f : A => Either[C,B]) : Either[C,B] = {
      val t0 = g(a)
      val tt  = t0.fold( { x => c(x) } , { x => f(x) } )
      tt
    }
    
  def conv[B](x: Throwable): Either[List[Throwable], B] = Left(List(x))

  def f0 = doX3(conv) _

  def convL[B](x: Throwable): Either[Long, B] = Left(100000)
  
  def f1 = doX3(convL) _
  

However, I now realize that:

  1. Because of the return type Try[A], conv will always have the input typed as Throwable
  2. To bind the types correctly conv must be passed as a parameter (cannot be any arbitrary function with the correct signature)
  3. The above is still not a solution because I cannot compile:
def f0[A,B,C](a: A, g: A => Try[A], f : A => Either[C,B]) = doX3(conv)(a, g, f)

because I get:

[error]  found   : A => Either[C,B]
[error]  required: ? => Either[List[Throwable],?]
[error]   def f0[A,B,C](a: A, g: A => Try[A], f : A => Either[C,B]) = doX3(conv)(a, g, f)
[error]                                                                                ^
[info] A => Either[C,B] <: ? => Either[List[Throwable],?]?

Now the question is why the above does not bind. When the compiler says:

``` ? => Either[List[Throwable],?] ``

Is that a:

``` X => Either[List[Throwable],Y] ``

or

``` X => Either[List[Throwable],X] ``

?

EDIT:

Something just occurred to me, so I tried:

    def doX3[A,B,C](c : Throwable => Either[C,B])(a: A, g: A => Try[A])(f : A => Either[C,B]) : Either[C,B] = {
      val t0 = g(a)
      val tt  = t0.fold( { x => c(x) } , { x => f(x) } )
      tt
    }
    
  def conv1[B](x: Throwable): Either[List[Throwable], B] = Left(List(x))

  def f0[A,B,C](a: A, g: A => Try[A], f : A => Either[C,B]) = doX3(conv1)(a, g)(f)

  def convL[B](x: Throwable): Either[Long, B] = Left(100000)
  
  def f1[A,B,C](a: A, g: A => Try[A], f : A => Either[C,B]) = doX3(convL)(a, g)(f)

And I get the error:

[error]  found   : A => Either[C,B]
[error]  required: A => Either[List[Throwable],?]
[error]   def f0[A,B,C](a: A, g: A => Try[A], f : A => Either[C,B]) = doX3(conv1)(a, g)(f)
[error]                                                                                 ^
[info] A => Either[C,B] <: A => Either[List[Throwable],?]?
[info] false
...
[error]  found   : A => Either[C,B]
[error]  required: A => Either[Long,?]
[error]   def f1[A,B,C](a: A, g: A => Try[A], f : A => Either[C,B]) = doX3(convL)(a, g)(f)
[error]                                                                                 ^
[info] A => Either[C,B] <: A => Either[Long,?]?

back to square 1.

TIA

Thanks for pointing out the g(a).fold(conv, f).