Created
February 24, 2018 18:28
-
-
Save yasuabe/ccc8329cc8defbe8451d5719f70d73ed to your computer and use it in GitHub Desktop.
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
import cats.data.{Kleisli, Nested, Tuple2K} | |
import cats.implicits._ | |
import cats.{Distributive, Functor, Id, Traverse, ~>} | |
// def distribute[G[_]: Functor, A, B](ga: G[A])(f: A => F[B]): F[G[B]] | |
// def cosequence[G[_]: Functor, A](ga: G[F[A]]): F[G[A]] = distribute(ga)(identity) | |
// Function0 ------------------------------ | |
// F = () => ? | |
val d0 = Distributive[() => ?] | |
// G = List, A = Char, B = String | |
// G[A] = List[Char], F[B] = () => String, F[G[B]] = () => List[String] | |
val afb0: Char => () => String = c => () => s"<$c>" | |
val ga0 = List('a', 'b') | |
d0.distribute(ga0)(afb0).apply // List[String] = List(<a>, <b>) | |
ga0.distribute(afb0).apply // List[String] = List(<a>, <b>) | |
// G = List, A = Char | |
// G[F[A]] = List[() => Char], F[G[A]] = () => List[Char] | |
val gfa0 = List.fill(3)(() => '7')å | |
d0.cosequence(gfa0).apply // List[Char] = List(7, 7, 7) | |
gfa0.cosequence[() => ?, Char].apply // List[Char] = List(7, 7, 7) | |
// Function1 ------------------------------ | |
// F = Int => ? | |
val d1 = Distributive[Int => ?] | |
// G = Option, A = Char, B = String | |
// G[A] = Option[Char], F[B] = Int => String, F[G[B]] = Int => Option[String] | |
val afb1: Char => Int => String = c => n => c.toString * n | |
val ga1 = Option('a') | |
d1.distribute(ga1)(afb1).apply(3) // List[String] = List(<a>, <b>) | |
ga1.distribute(afb1).apply(3) // List[String] = List(<a>, <b>) | |
// G = Option, A = String | |
// G[F[A]] = List[() => Char], F[G[A]] = () => List[Char] | |
val gfa1: Option[Int => String] = Option(n => "a" * n) | |
d1.cosequence[Option, String](gfa1).apply(3) // List[Char] = List(7, 7, 7) | |
d1.cosequence[Option, String](None).apply(3) // None | |
gfa1.cosequence[Int => ?, String].apply(4) // List[Char] = List(7, 7, 7) | |
// Nested ------------------------------ | |
// F = Nested[() => ?, Int => ?, A] | |
type FN[A] = Nested[() => ?, Int => ?, A] | |
val dn = Distributive[FN] | |
// G = Option, A = Char, B = String | |
// G[A] = Option[Char], F[B] = Int => String, F[G[B]] = Int => Option[String] | |
val afbn: Char => FN[String] = c => Nested(() => c.toString * _) | |
val gan = Option('a') | |
dn.distribute(gan)(afbn).value()(5) // Some(aaaaa) | |
gan.distribute(afbn).value()(3) // Some(aaa) | |
dn.distribute(gan)(afbn) | |
.map(_.map(s => s"<$s>")) // <-- (a) | |
.value()(3) // Some(<aaa>) | |
// G = List, A = String | |
// G[F[A]] = List[FN[String]], F[G[A]] = FN[List[String]] | |
val gfan: List[FN[String]] = List(Nested(() => "n" * _), Nested(() => "m" * _)) | |
val nested = dn.cosequence[List, String](gfan) | |
nested.value()(3) // List(nnn, mmm) | |
nested.map(os => s"<$os>").value()(2) // <List(nn, mm)> | |
gfan.cosequence[FN, String].value()(2) // List(nn, mm) | |
val func0ToId: Function0 ~> Id = new (Function0 ~> Id) { | |
override def apply[A](fa: () => A) = fa() | |
} | |
gan.distribute(afbn).mapK(func0ToId).value(3) // Some(aaa) | |
// Kleisli ------------------------------ | |
// F = Kleisli[() => ?, Int, A] | |
type FK[A] = Kleisli[() => ?, Int, A] | |
val dk = Distributive[FK] | |
// G = Option, A = Char, B = String | |
// G[A] = Option[Char], F[B] = Int => String, F[G[B]] = Int => Option[String] | |
val afbk: Char => FK[String] = c => Kleisli(n => () => c.toString * n) | |
val gak = Option('a') | |
dk.distribute(gak)(afbk).run(7)() // Some(aaaaaaa) | |
gak.distribute(afbk).run(7)() // Some(aaaaaaa) | |
// G = Option, A = String | |
// G[F[A]] = Option[FK[String]], F[G[A]] = FK[Option[String]] | |
val gfak: Option[FK[String]] = Option(Kleisli(n => () => "k" * n)) | |
dk.cosequence[Option, String](gfak).run(8)() // Some(kkkkkkkk) | |
dk.cosequence[Option, String](None).run(8)() // None | |
gfak.cosequence[FK, String].run(6)() // Some(kkkkkk) | |
// Tuple2K -------------------------- | |
// F = Tuple2K[Int => ?, Boolean => ?, A] | |
type FT[A] = Tuple2K[Int => ?, Boolean => ?, A] | |
val dt = Distributive[FT] | |
// G = Option, A = Char, B = String | |
// G[A] = Option[Char], F[B] = Int => String, F[G[B]] = Int => Option[String] | |
val afbt: Char => FT[String] = c => Tuple2K(c.toString * _, b => s"<$c, $b>") | |
val gat = Option('a') | |
dt.distribute(gat)(afbt).first(2) // Some(aa) | |
gat.distribute(afbt).second(true) // Some(<a, true>) | |
// G = Option, A = String | |
// G[F[A]] = Option[FK[String]], F[G[A]] = FK[Option[String]] | |
val gfat: Option[FT[String]] = Option(Tuple2K(n => s"<n>", b => s"<$b>")) | |
dt.cosequence[Option, String](None).first(2) // None | |
gfat.cosequence[FT, String].second(false) // Some(<false>) | |
// compose -------------------------- | |
type TC[A] = Int => Double => A | |
val composed: Distributive[TC] = Distributive[Int => ?].compose[Double => ?] | |
def f(o: Option[TC[String]]) = composed.cosequence[Option, String](o).apply(3)(0.14) | |
f(Option(n => d => s"π ≒ ${n + d}")) // Some(π ≒ 3.14) | |
f(None) // None | |
// traverse ---------------------------------- | |
val h: Double => Int => String = d => n => s"${n+d}" | |
val o = Option(0.14) | |
val s1 = Distributive[Int => ?].distribute[Option, Double, String](o)(h) | |
val t1 = Traverse [Option] .traverse [Int => ?, Double, String](o)(h) | |
assert(s1(3) == t1(3)) // 共に Some(3.14) | |
val of: Option[Int => String] = Option(n => s"n = $n") | |
val s2 = Distributive[Int => ?].cosequence[Option, String](of) | |
val t2 = Traverse [Option] .sequence [Int => ?, String](of) | |
assert(s2(100) == t2(100)) // 共に Some(n = 100) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment