Skip to content

Instantly share code, notes, and snippets.

@erikerlandson
Last active March 26, 2018 16:48
Show Gist options
  • Save erikerlandson/a784411bc2bce5a8fbafddc3cc3e0b3c to your computer and use it in GitHub Desktop.
Save erikerlandson/a784411bc2bce5a8fbafddc3cc3e0b3c to your computer and use it in GitHub Desktop.
sifting
scala> :load /home/eje/sift.scala
Loading /home/eje/sift.scala...
defined module sift
defined module demo
scala> import sift._
import sift._
scala> val r = Sifted.seq(demo.dirty).map(_.map(_.toDouble)).filter(_(0) > 1).map(_(1))
r: sift.SiftedSeq[Double,scala.collection.immutable.Vector,(scala.collection.immutable.Vector[scala.collection.immutable.Vector[Double]], (scala.collection.immutable.Vector[scala.collection.immutable.Vector[Double]], (scala.collection.immutable.Vector[scala.collection.immutable.Vector[String]], List[Nothing])))] = SiftedSeq(Vector(5.0),(Vector(Vector(3.0)),(Vector(Vector()),(Vector(Vector(2, 3, z)),List()))))
scala> r.passed
res0: scala.collection.immutable.Vector[Double] = Vector(5.0)
scala> r.retained
res1: (scala.collection.immutable.Vector[scala.collection.immutable.Vector[Double]], (scala.collection.immutable.Vector[scala.collection.immutable.Vector[Double]], (scala.collection.immutable.Vector[scala.collection.immutable.Vector[String]], List[Nothing]))) = (Vector(Vector(3.0)),(Vector(Vector()),(Vector(Vector(2, 3, z)),List())))
object sift {
import scala.language.reflectiveCalls
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom
import scala.util.Either
type Seive[T, U] = T => Either[T, U]
def liftToSeive[T, U](f: T => U): Seive[T, U] = {
(t: T) => try {
Right(f(t))
} catch {
case _: Throwable => Left(t)
}
}
case class SiftedSeq[T, S[E] <: SeqLike[E, S[E]], R](passed: S[T], retained: R) {
def map[U](f: T => U)(implicit cbf1: CanBuildFrom[S[T], Either[T,U], S[Either[T,U]]], cbf2: CanBuildFrom[S[Either[T,U]], Either[T,U], S[Either[T,U]]], cbf3: CanBuildFrom[S[Either[T,U]], U, S[U]], cbf4: CanBuildFrom[S[Either[T,U]], T, S[T]]): SiftedSeq[U, S, (S[T], R)] = {
val s = passed.map(liftToSeive(f))
val p = s.filter(_.isRight).map(_.right.get)
val r = s.filter(_.isLeft).map(_.left.get)
SiftedSeq[U, S, (S[T], R)](p, (r, retained))
}
def filter(f: T => Boolean)(implicit cbf1: CanBuildFrom[S[T], T, S[T]]): SiftedSeq[T, S, (S[T], R)] = {
val fs = liftToSeive(f)
val p = passed.filter { e =>
val t = fs(e)
t.isRight && t.right.get
}
val r = passed.filter { e => fs(e).isLeft }
SiftedSeq[T, S, (S[T], R)](p, (r, retained))
}
}
object Sifted {
def seq[T, S[E] <: SeqLike[E, S[E]]](data: S[T]) = SiftedSeq[T, S, List[Nothing]](data, Nil)
}
}
object demo {
val dirty = Vector(
Vector("1", "2", "3"),
Vector("2", "3", "z"),
Vector(),
Vector("3"),
Vector("4", "5")
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment