Reputation: 1128
I'm trying to write a method which uses the isEmpty
method on types String
, Option
and List
. These classes don't share a common base trait with that method, so I've tried to pass an implicit EmptyChecker
in with them:
trait EmptyChecker[Field] {
def isEmpty(data: Field): Boolean
}
implicit val StringEmptyChecker: EmptyChecker[String] = new EmptyChecker[String] {
def isEmpty(string: String): Boolean = string.isEmpty
}
def printEmptiness[Field](field: Field)(implicit emptyChecker: EmptyChecker[Field]): Unit = {
if (emptyChecker.isEmpty(field))
println("Empty")
else
println("Not empty")
}
printEmptiness("abc") // Works fine
The String
empty checker works fine, but I've hit problems with making empty checkers for type constructors like Option
and List
.
For example, Option
doesn't work:
implicit val OptionChecker: EmptyChecker[Option[_]] = new EmptyChecker[Option[_]] {
def isEmpty(option: Option[_]): Boolean = option.isEmpty
}
// Both fail compilation: "could not find implicit value for parameter emptyChecker: EmptyChecker[Some[Int]]
printEmptiness(Some(3))
printEmptiness[Option[Int]](Some(3))
If I use a specific Option[Int]
checker, it works a little better, but is a bit ugly:
implicit val OptionIntChecker: EmptyChecker[Option[Int]] = new EmptyChecker[Option[Int]] {
def isEmpty(optionInt: Option[Int]): Boolean = optionInt.isEmpty
}
// Fails like above:
printEmptiness(Some(3))
// Passes compilation:
printEmptiness[Option[Int]](Some(3))
So my question is: is it possible to make a single EmptyChecker
for each Option
and List
type and have them work with my method without needing to explicitly declare the type whenever I call it? I'm trying to get a type safe duck typing effect.
I'm using scala 2.11.6.
Thanks in advance!
Upvotes: 2
Views: 49
Reputation: 8932
The source of your problem is that the type of Some(1)
is Some[Int]
, not Option[Int]
. There are a couple of ways around this; you can explicitly upcast the expression with a type ascription: printEmptiness(Some(3): Option[Int])
. Alternatively, you can define a helper method to do this for you automatically, and if you're using Scalaz, there's one of these provided:
import scalaz.syntax.std.option._
printEmptiness(3.some)
Furthermore if you do use Scalaz, you may find looking at the PlusEmpty
/ApplicativePlus
/MonadPlus
type classes useful.
Upvotes: 3