Too specific an object for first argument of foldLeft

I have a call to foldLeft, where the 2nd argument is a function (Bdd,Int)=>Bdd,
but the first argument BddTrue is an object defined as below.

bitsToSet(truthTable).map(_ - 1).foldLeft(BddTrue)((b1:Bdd,i2:Int) => And(b1,i2))

The compiler message I get is:

Error:(14, 78) type mismatch;
 found   : Bdd
 required: BddTrue.type
    bitsToSet(truthTable).map(_ - 1).foldLeft(BddTrue)((b1:Bdd,i2:Int) => And(b1,i2))

BddTrue is defined as follows.

abstract class BddTerm extends Bdd {
  ...
}
object BddTrue extends BddTerm {
 ...
}

Is there some way for me to decorate the first argument of foldLeft to make the compiler happy? Because yes indeed, BddTrue is an object of type Bdd

bitsToSet(truthTable).map(_ - 1).foldLeft(BddTrue: Bdd)((b1:Bdd,i2:Int) => And(b1,i2))
1 Like

Great I was trying BddTrue[Bdd] and BddTrue.asInstanceOf[Bdd]

Yeah, this isn’t an unusual problem. The compiler’s type inference is smart, but sometimes gets locked into an overly-specific type too early, so that the general type then fails later on. As shown by @curoli, the solution is usually to give the compiler a hint about the more general type that you intended in the first place.

I need to remember that syntax. The : is normally used in a declaration, I wan’t aware it could be used in an evaluation position.

…alternatively: .foldLeft[Bdd](BddTrue)((b, i) => ...

1 Like

ahh foldLeft[Bdd], that was why I was remembering the square brackets.

To be clear, if you have an expression with a type ascription like expr: A you are not casting. You are ascribing a more general type than what would be inferred, but it still must typecheck (unlike .asInstanceOf which is unchecked and is therefore very dangerous).

1 Like

great. so what’s the different between foldLeft[T](z)(...) and foldLeft(z:T)(...) ? is it the same or is there some semantic difference as well?

The difference in how they arrive at the same result is mostly academic.

foldLeft[T](z) fixes the type parameter of the foldLeft to T, which makes the expected type of z into T, which the typechecker checks.

foldLeft(z: T) makes the expected type of z be T, which the typechecker checks, and infers the type parameter of foldLeft should be T too.

ah yes, and for foldLeft it is the first argument who has type T. accident of foldLeft that the two are the same thing in the end.