Note that there are some explanatory texts on larger screens.

plurals
  1. POSimplifying type annotations
    primarykey
    data
    text
    <p>I've created a pimp method, <code>collate</code>, that's usable from any <code>Traversable</code> or any type that can be coerced to a traversable as per the following example:</p> <pre><code>val ints = List(0,9,4,5,-3,-5,6,5,-2,1,0,6,-3,-2) val results = ints collate { case i: Int if(i &lt; 0) =&gt; i.floatValue } andThen { case i: Int if(i&gt;5) =&gt; i.toString } andThen { case i: Int if(i==0) =&gt; i } toTuple /* results: (List[Float], List[java.lang.String], List[Int], List[Int]) = (List(-3.0, -5.0, -2.0, -3.0, -2.0),List(9, 6, 6),List(0, 0),List(4, 5, 5, 1)) */ </code></pre> <p>Think of it as the unholy spawn of a union 'twixt <code>collect</code> and <code>partition</code>, if you will...</p> <p>It's defined like this:</p> <pre><code>import collection.generic.CanBuildFrom class Collatable[Repr &lt;% Traversable[T], T](xs: Repr) { // Results handling stuff, bit like a poor-man's HList, feel free to skip... trait Results { def remainder: Repr type Append[That] &lt;: Results def append[That](tup: (That, Repr)): Append[That] def andThen[R, That](pf: PartialFunction[T, R]) (implicit matchesBuilder: CanBuildFrom[Repr, R, That], remainderBuilder: CanBuildFrom[Repr, T, Repr] ) = { val more = (new Collatable[Repr,T](remainder)).collateOne[R,That](pf) append(more) } } case class Results9[M1,M2,M3,M4,M5,M6,M7,M8,M9]( m1: M1, m2: M2, m3: M3, m4: M4, m5: M5, m6: M6, m7: M7, m8: M8, m9: M9, remainder: Repr) extends Results { implicit def toTuple = (m1, m2, m3, m4, m5, m6, m7, m8, m9, remainder) def append[That](tup: (That, Repr)) = error("too many") } // ... skip a bit, still in results logic ... case class Results2[M1,M2]( m1: M1, m2: M2, remainder: Repr) extends Results { implicit def toTuple = (m1, m2, remainder) type Append[That] = Results3[M1,M2,That] def append[That](tup: (That, Repr)) = Results3(m1, m2, tup._1, tup._2) } case class Results1[M1](matches: M1, remainder: Repr) extends Results { implicit def toTuple = (matches, remainder) type Append[That] = Results2[M1, That] def append[That](tup: (That, Repr)) = Results2(matches, tup._1, tup._2) } // and now... Our feature presentation! def collateOne[R, That](pf: PartialFunction[T, R]) (implicit matchesBuilder: CanBuildFrom[Repr, R, That], remainderBuilder: CanBuildFrom[Repr, T, Repr] ) = { val matches = matchesBuilder(xs) val remainder = remainderBuilder(xs) for (x &lt;- xs) if (pf.isDefinedAt(x)) matches += pf(x) else remainder += x (matches.result, remainder.result) } def collate[R, That](pf: PartialFunction[T, R]) (implicit matchesBuilder: CanBuildFrom[Repr, R, That], remainderBuilder: CanBuildFrom[Repr, T, Repr] ): Results1[That] = { val tup = collateOne[R,That](pf) Results1(tup._1, tup._2) } } object Collatable { def apply[Repr, T](xs: Repr)(implicit witness: Repr =&gt; Traversable[T]) = { new Collatable[Repr, T](xs) } } implicit def traversableIsCollatable[CC[X] &lt;: Traversable[X], A](xs: CC[A]) = Collatable[CC[A], A](xs) implicit def stringIsCollatable(xs: String) = Collatable[String, Char](xs) </code></pre> <p>Conceptually, it's not all that daunting once you understand how <code>CanBuildFrom</code> works, but I'm finding that it's it's overwhelmed by boilerplate - especially with the implicits.</p> <p>I know that I could simplify the ResultX logic a great deal by using an HList, and that's something I probably will do, so that piece of code doesn't especially worry me.</p> <p>I also know that I could make my life <em>significantly</em> easier if I was able to constrain <code>Repr</code> as a subtype of <code>Traversable</code>. But I refuse do that, because then it couldn't be used against Strings. By the same token, I'd also like to avoid forcing the partial functions to return a subtype of T - although this is less of a concern as I could always break my logic into distinct collate and map operations.</p> <p>More concerning is <code>CanBuildFrom[Repr, T, Repr]</code>, which I seem to keep repeating, and which obscures the important stuff from my method signatures. This is something I feel sure can be defined just once at the class level, but I haven't yet found a way to make it work.</p> <p>Any ideas?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload