Skip to content

Instantly share code, notes, and snippets.

@notxcain
Created October 15, 2018 13:03
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 notxcain/8f22c524bcc476452a9f3b3f6f7c30eb to your computer and use it in GitHub Desktop.
Save notxcain/8f22c524bcc476452a9f3b3f6f7c30eb to your computer and use it in GitHub Desktop.
import cats.{ Comonad, Monad }
import cats.effect.{ Concurrent, Resource, Timer }
import cats.implicits._
import scala.concurrent.duration.FiniteDuration
object Ex {
final case class Point(x: Long, y: Long)
final case class Direction(value: Double)
final case class Store[S, A](view: S => A, state: S) {
def extract: A = view(state)
def coflatMap[B](f: Store[S, A] => B): Store[S, B] = Store(s => f(Store(view, view(s))), state)
def map[B](f: A => B): Store[S, B] = Store(f.compose(view), state)
def duplicate: Store[S, Store[S, A]] = Store(s => Store(view, s), state)
def move(s: S): Store[S, A] = duplicate.view(s)
}
object Store {
implicit def comonad[S]: Comonad[Store[S, ?]] = new Comonad[Store[S, ?]] {
override def extract[A](x: Store[S, A]): A = x.extract
override def coflatMap[A, B](fa: Store[S, A])(f: Store[S, A] => B): Store[S, B] =
fa.coflatMap(f)
override def map[A, B](fa: Store[S, A])(f: A => B): Store[S, B] = fa.map(f)
}
}
trait Co[F[_], A] {
def run[R](f: F[A => R]): R
}
object Co {
implicit def monad[F[_]](implicit F: Comonad[F]): Monad[Co[F, ?]] = new Monad[Co[F, ?]] {
override def pure[A](x: A): Co[F, A] = new Co[F, A] {
override def run[R](f: F[A => R]): R = F.extract(f)(x)
}
override def flatMap[A, B](fa: Co[F, A])(f: A => Co[F, B]): Co[F, B] = new Co[F, B] {
override def run[R](fbr: F[B => R]): R =
fa.run(fbr.map(_ => (x: A) => f(x).run(fbr)))
}
override def tailRecM[A, B](a0: A)(f: A => Co[F, Either[A, B]]): Co[F, B] = flatMap(f(a0)) {
case Left(a) => tailRecM(a)(f)
case Right(b) => pure(b)
}
}
def select[F[_], A, B](co: Co[F, A => B], fa: F[A])(implicit F: Comonad[F]): F[B] = null
}
trait Pairing[F[_], G[_]] {
def pair[A, B, C](abc: A => B => C, fa: F[A], gb: G[B]): C
def move[A, B](wa: G[A], mb: F[B])(implicit W: Comonad[G]): G[A] =
pair(Function.const(identity[G[A]]), mb, W.coflatten(wa))
}
final case class MooreT[I, A](current: A, run: I => MooreT[I, A]) {
def coflatMap[B](f: MooreT[I, A] => B): MooreT[I, B] =
MooreT(f(this), i => run(i).coflatMap(f))
def map[B](f: A => B): MooreT[I, B] = MooreT(f(current), i => run(i).map(f))
}
object MooreT {
implicit def comonad[I]: Comonad[MooreT[I, ?]] = new Comonad[MooreT[I, ?]] {
override def extract[A](x: MooreT[I, A]): A = x.current
override def coflatMap[A, B](fa: MooreT[I, A])(f: MooreT[I, A] => B): MooreT[I, B] =
fa.coflatMap(f)
override def map[A, B](fa: MooreT[I, A])(f: A => B): MooreT[I, B] =
fa.map(f)
}
}
sealed abstract class Action[+I, +A]
object Action {
final case class Pure[A](a: A) extends Action[Nothing, A]
final case class Run[I, A](action: I, next: Action[I, A]) extends Action[I, A]
implicit def pairing[I]: Pairing[Action[I, ?], MooreT[I, ?]] = new Pairing[Action[I, ?], MooreT[I, ?]] {
override def pair[A, B, C](abc: A => B => C,
fa: Action[I, A],
gb: MooreT[I, B]): C = fa match {
case Pure(a) => abc(a)(gb.current)
case Run(a, r) => pair(abc, r, gb.run(a))
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment