3

So I have the following method that wraps a Seq-like object in an Option.

def noneIfEmpty[S <% Seq[_]](seq: S): Option[S] = {
  if (seq.isEmpty) None else Some(seq)
}

I'd like to be able to use this method to transform the results of computations wrapped in a Try. Say I do this with a List[Int]:

scala> val tryList = Try(List(1,2,3))
tryList: scala.util.Try[List[Int]] = Success(List(1, 2, 3))

I should be able to use noneIfEmpty to map the Try[List[Int]] to a Try[Option[List[Int]]]. This works fine if I use an anonymous function and explicitly pass the list to noneIfEmpty...

scala> tryList map (list => noneIfEmpty(list))
res1: scala.util.Try[Option[List[Int]]] = Success(Some(List(1, 2, 3)))

...but it breaks if I try to pass noneIfEmpty as a partially applied function.

scala> tryList map noneIfEmpty _
<console>:40: error: No implicit view available from S => Seq[_].
              tryList map noneIfEmpty _
                          ^

It also works fine if I narrow noneIfEmpty to only accept lists:

scala> def noneIfEmptyList[A](list: List[A]): Option[List[A]] = noneIfEmpty(list)
noneIfEmptyList: [A](list: List[A])Option[List[A]]
scala> tryList map noneIfEmptyList _
res2: scala.util.Try[Option[List[Int]]] = Success(Some(List(1, 2, 3)))

What's going on here? Is there some kind of type erasure voodoo at work or something?

zh2l4d7s
  • 97
  • 1
  • 9

1 Answers1

5

The issue is that a view bound is syntactic sugar for an implicit parameter, so your method is really

def noneIfEmpty[S](seq: S)(implicit ev: S => Seq[_]): Option[S]

Unfortunately you cannot partially apply a method that takes implicit parameters, as the process of eta-expansion (i.e. converting a method to a function) requires implicits to be resolved in advance.

Ultimately your problem reduces to this one.

Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235