Skip to content

Instantly share code, notes, and snippets.

@kubukoz
Last active March 24, 2017 14:37
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 kubukoz/69257fd31a5ae96b855e3c33d84325e4 to your computer and use it in GitHub Desktop.
Save kubukoz/69257fd31a5ae96b855e3c33d84325e4 to your computer and use it in GitHub Desktop.
import cats.instances.list._
import Flatten.Level.Aux
import scala.language.higherKinds
object Flatten {
import cats.Monad
import cats.syntax.flatMap._
trait Level {
type From[_[_], _]
type To[_[_], _]
def convert[U, M[_]: Monad](f: From[M, U]): To[M, U]
}
object Level {
type Aux[FFrom[_[_], _], TTo[_[_], _]] = Level {
type From[M[_], T] = FFrom[M, T]
type To[M[_], T] = TTo[M, T]
}
}
def flatten[L <: Level](implicit levelAux: Level.Aux[L#From, L#To]): Aux[L#From, L#To] = levelAux
trait Two extends Level {
type From[M[_], T] = M[M[M[T]]]
type To[M[_], U] = M[U]
override def convert[U, M[_]: Monad](f: M[M[M[U]]]): M[U] = f.flatten.flatten
}
trait One extends Level {
override type From[M[_], T] = M[M[T]]
override type To[M[_], T] = M[T]
override def convert[U, M[_]: Monad](f: M[M[U]]): M[U] = f.flatten
}
implicit object Two extends Two
implicit object One extends One
val ints: List[List[List[Int]]] = List(List(List(5), List(10)))
//these types can be inferred automatically
val once: List[List[Int]] = flatten[One].convert(ints)
val twice: List[Int] = flatten[One].convert(once)
val twice3: List[Int] = flatten[Two].convert(ints)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment