Skip to content

Instantly share code, notes, and snippets.

@sortega
Created November 17, 2022 18:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sortega/baa53dd69f97e9fd94785aca983c2aad to your computer and use it in GitHub Desktop.
Save sortega/baa53dd69f97e9fd94785aca983c2aad to your computer and use it in GitHub Desktop.
What if we needed Luigi-style input/output flattening but in a type safe way?
package flattening
import scala.annotation.implicitNotFound
object Flattener {
def flatten[A]: PartiallyAppliedFlattener[A] = new PartiallyAppliedFlattener
final class PartiallyAppliedFlattener[A] {
def apply[B](value: B)(implicit ev: Flattenable[A, B]): List[A] = ev(value)
}
}
@implicitNotFound("Cannot flatten ${B} into List[${A}]")
trait Flattenable[+A, -B] {
def apply(value: B): List[A]
}
object Flattenable {
implicit def identityFlatten[A]: Flattenable[A, A] = value => List(value)
implicit def listFlatten[A, B](implicit ev: Flattenable[A, B]): Flattenable[A, List[B]] =
list => list.flatMap(ev.apply)
implicit def mapFlatten[K, A, B](implicit ev: Flattenable[A, B]): Flattenable[A, Map[K, B]] =
map => map.values.toList.flatMap(ev.apply)
implicit def traversableOnceFlatten[A, B](implicit
ev: Flattenable[A, B]
): Flattenable[A, TraversableOnce[B]] =
traversable => traversable.flatMap(ev.apply).toList
}
object FlattenerDemo extends App {
println(Flattener.flatten[String]("hello"))
println(Flattener.flatten[String](List("he", "llo")))
println(Flattener.flatten[Char](List("he".toList, "llo".toList)))
println(Flattener.flatten[String](Map(1 -> "he", 2 -> "llo")))
println(Flattener.flatten[String](List(Map(1 -> "he", 2 -> "llo"), Map(3 -> "!"))))
println(Flattener.flatten[String](Map(1 -> List("he"), 2 -> List("llo", "!"))))
println(Flattener.flatten[String](List(Vector("he"), Vector("llo", "!"))))
// Next line fails to compile with error: Cannot flatten scala.collection.immutable.Set[Int] into List[String]
// println(Flattener.flatten[String](Set(12)))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment