I have defined some top level objects in a simply hierarchy because I want their `apply`

methods to always behave the same way in several base cases. Because of the `apply`

methods defined in `BinaryOperation`

I can call any of the objects `And`

, `Or`

, `Xor`

etc as if they were functions, and I can pass *exactly* two arguments, either of which is a positive integer and either of which is a `Bdd`

. Thus I can evaluate an expression such as `Or(And(1,2),And(3,Xor(2,4)))`

. The integers are treated as Boolean variables such as x1, x2, x3, x4. The result of this evaluation is an object which represents the Boolean function `(x1 and x2) or (x3 and (x2 xor x4))`

.

This works great, but Iâ€™m limited to only use binary functions. Iâ€™d like to have varargs semantics. Iâ€™d like to say `And(Or(1,2),Or(2,3),Or(1,3),Or(3,4))`

, but Iâ€™d also like to use `And(1,2,3,Or(4,5,And(1,2)),Xor(2,5))`

.

I canâ€™t figure out how to have a varargs function which accepts arguments which are each either `Integer`

or `Bdd`

. Can this be done somehow simply with varargs `apply`

in the `BinaryOperation`

class whose implementation is a call to `fold`

? My guess is the answer is sadly â€śNoâ€ť because Scala does not support union types. I can declare a parameter as `Integer | Bdd`

.

If that supposition is correct, then can I do it with an implicit conversion? I.e., can I have the apply method implicitly convert any `Integer n`

to a `Bdd`

by calling the constructor `Bdd(n)`

, thus also eliminating the need for the 4 `apply`

methods in the `BinaryOperator`

class? And also eliminating the need to implement the Boolean operators as objects, allowing them to be implemented as regular functions?

```
sealed abstract class BinaryOperation() {
def apply(b1: Bdd, b2: Bdd): Bdd
def apply(l1: Int, l2: Int): Bdd = {
this (Bdd(l1), Bdd(l2))
}
def apply(l1: Int, b2: Bdd): Bdd = {
this (Bdd(l1), b2)
}
def apply(b1: Bdd, l2: Int): Bdd = {
this (b1, Bdd(l2))
}
}
object And extends BinaryOperation {
def apply(b1: Bdd, b2: Bdd): Bdd = {
(b1, b2) match {
case (b1, b2) if (b1 eq b2) => b1
case (BddTrue, _) => b2
case (BddFalse, _) => BddFalse
case (_, BddTrue) => b1
case (_, BddFalse) => BddFalse
case (b1: BddNode, b2: BddNode) => Bdd.bddOp(this, b1, b2)
}
}
}
object Or extends BinaryOperation {
def apply(b1:Bdd,b2:Bdd):Bdd = {
...
}
}
object Xor extends BinaryOperation {
def apply(b1:Bdd,b2:Bdd):Bdd = {
...
}
}
object Xnor extends BinaryOperation {
def apply(b1:Bdd,b2:Bdd):Bdd = {
...
}
}
object AndNot extends BinaryOperation {
def apply(b1:Bdd,b2:Bdd):Bdd = {
...
}
}
```