2016-11-18

xacid: (Default)
2016-11-18 12:07 am
Entry tags:

and still SK

import cats._
import cats.data._
import cats.implicits._

import scala.concurrent._
import scala.concurrent.duration.Duration._
import ExecutionContext.Implicits.global

object Sk extends App {
  val PLUS = ((_: Int) + (_: Int)).curried

  trait SK[F[_]] {
    type ->>[A, B] = Kleisli[F, A, B]

    def S[E, A, B]: E ->> (A => B) =>
      E ->> A => E ->> B

    def K[E, A]: (E => A) => E ->> (E => A)

    def I[A]: A ->> A
  }

  object SK {
    def apply[F[_] : SK] = implicitly[SK[F]]

    def S[F[_] : SK, E, A, B](f: SK[F]# ->>[E, A => B])
                             (a: SK[F]# ->>[E, A]) =
      SK[F].S(f)(a)

    def K[F[_] : SK, E, A](f: E => A) = SK[F].K(f)

    def I[F[_] : SK, A] = SK[F].I[A]
  }

  implicit def ska[F[_] : Applicative]: SK[F] =
    new SK[F] {
      def AP[E] = Applicative[E ->> ?]

      def S[E, A, B] = AP[E].ap[A, B]

      def K[E, A] = AP[E].pure[E => A]

      def I[A] = Kleisli.ask[F, A]
    }

  import SK._

  def answer[F[_] : SK] = S(S(K(PLUS))(I))(I)

  def main[F[_] : SK : Functor] =
    answer[F].map(println)

  main[Id].apply(21)
  
  Await.ready(main[Future].apply(21), Inf)

}