Skip to content

Instantly share code, notes, and snippets.

@yasuabe
Created March 2, 2018 15:04
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 yasuabe/3a11d9ad827f104feefb45785c3e0bbd to your computer and use it in GitHub Desktop.
Save yasuabe/3a11d9ad827f104feefb45785c3e0bbd to your computer and use it in GitHub Desktop.
import cats.MonoidK
import scala.util.Try
import cats.data.Kleisli
import cats.syntax.option._
import cats.syntax.either._
import cats.syntax.compose._
import cats.syntax.foldable._
import cats.syntax.arrow._
import cats.syntax.arrowChoice._
import cats.instances.option._
import cats.instances.list._
import cats.arrow._
type KleisliOption[A, B] = Kleisli[Option, A, B]
val toInt = Kleisli((s: String) => Try(s.trim.toInt).toOption)
val invert = Kleisli((n: Int) => n.some.filter(_ != 0).map(1.0 / _))
val toPercentile = Kleisli((d: Double) => s"${d * 100}%".some)
// Compose --------------------------------
val cko = Compose[KleisliOption]
(toInt >>> invert >>> toPercentile).run("5") // "5" → 5 → 0.2 → "20.0%"
cko.compose(toPercentile, invert <<< toInt).run("5") // same as above
(invert <<< toInt).run("0") // None
cko.andThen(toInt, invert).run("foo") // None
val braces = Kleisli((s: String) => s"{$s}".some)
val brackets = Kleisli((s: String) => s"[$s]".some)
cko.algebraK.combineK[String](braces, brackets).run("foo") // Some({[foo]})
cko.algebra[String].combine(braces, brackets).run("bar") // Some({[bar]})
// Category -------------------------------
val cat = Category[KleisliOption]
cat.id[String].run("foo") // Some(foo)
type EndoKleisliOption[A] = KleisliOption[A, A]
implicit val monoidK: MonoidK[EndoKleisliOption] = cat.algebraK
cat.algebraK.empty[Int].run(100) // Some(100)
val ks: List[EndoKleisliOption[String]] = List(brackets, braces, brackets)
ks.foldK.run("baz") // Some([{[baz]}])
// Choice -------------------------------
val choice = Choice[KleisliOption]
val toDouble = Kleisli((s: String) => Try(s.trim.toDouble).toOption)
val h = choice.choice[String, Int, Double](toDouble, invert)
h(Right(100)) // Some(0.01)
h(Right(0)) // None
h(Left("NaN")) // Some(NaN)
choice.codiagonal("abc".asRight[String]) // Some(abc)
choice.codiagonal("error".asLeft[String]) // Some(error)
//import cats.arrow.Choice.ops._
//(toDouble ||| invert)(Left("3.14")) // Some(3.14)
//(toDouble ||| invert)(Left("foo")) // None
def choice(e: Either[String, Int]) = {
import cats.arrow.Choice.ops.toAllChoiceOps
(toDouble ||| invert).run(e)
}
choice(Left("3.14")) // Some(3.14)
choice(Left("foo")) // None
// Profunctor -------------------------------
val prof = Profunctor[KleisliOption]
val l = (s: String) => s.toInt
val r = (d: Double) => s"${d * 100}%"
prof.dimap[Int, Double, String, String](invert)(l)(r)("5") // Some(20.0%)
prof.lmap[Int, Double, String](invert)(l)("10") // Some(0.1)
prof.rmap[Int, Double, String](invert)(r)(2) // Some(50.0%)
// Strong -------------------------------
val strong = Strong[KleisliOption]
strong.first(invert).run((10, 0.5)) // Some((0.1, 0.5))
strong.second(toPercentile).run((10, 0.5)) // Some((10, 50%))
(strong.first(invert) >>> strong.second(toPercentile))
.run((10, 0.5)) // Some((0.1, 50%))
// Arrow -------------------------------
val arrow = Arrow[KleisliOption]
val length = arrow.lift((s: String) => s.length)
arrow.split(invert, length)((10, "test")) // Some((0.1, 4))
arrow.merge(length, toInt)("123") // Some((3, 123))
(invert *** length *** toPercentile).run(((10, "test"), 0.01))
// Some(((0.1, 4), 1.0%))
(length &&& toInt).run("-") // None
// ArrowChoice -------------------------------
val arrowChoice = ArrowChoice[KleisliOption]
arrowChoice.choose(invert)(length)(Left(10)) // Some(Left(0.1))
(invert +++ length)(Right("right")) // Some(Right(5))
arrowChoice.left(invert)(Left(10)) // Some(Left(0.1))
length right Right("right") // Some(Right(5))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment