Created
November 17, 2022 18:17
-
-
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?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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