nicolasstucki/multisets

Map returning Iterable[T] instead of Bag[T]

Closed this issue · 7 comments

In specific circumstances, Bag.map returns an Iterable[T], and I can't for the life of me figure out why. To reproduce in REPL:

import scala.collection.Bag

implicit val config = Bag.configuration.compact[String]

abstract class Expr { def substitute(substitutions: (String, Expr)*): Expr }
case class Sum(addends: Bag[Expr]) extends Expr {
    override def substitute(substitutions: (String, Expr)*) = Sum(addends.map { _.substitute(substitutions: _*) })
}
// error   : type mismatch;
// found   : Iterable[Expr]
// required: scala.collection.Bag[Expr]
//       override def substitute(substitutions: (String, Expr)*) = Sum(addends.map { _.substitute(substitutions: _*) })
//                                                                                 ^

In an actual file, explicitly typing the method as addends.map[Expr, Bag[Expr]] made it work, but this fails in the REPL.

Try using scala.collection.immutable.Bag.

You can also add import scala.collection.immutable.Bag._

Didn't work, same error.

You need a implicit val config = Bag.configuration.compact[Expr] not compact[String].

The reason why it was creating the Iterable was because the implicit parameter search for the canBuildFrom (the thing that generates new builders) could find it for iterable (because it is one of the predefs). But could not find one for the bag, because the canBuildFrom requires te configuration to be instantiated, in this case a configuration for Expr that was nowhere to be found.

Oh, sorry, didn't see that when copy-pasting the config line from the tutorial.

@dimitriye98 you could also try to use the following to avoid these situations.

implicit def config[T] = Bag.configuration.compact[T]