Created
October 15, 2018 13:03
-
-
Save notxcain/8f22c524bcc476452a9f3b3f6f7c30eb to your computer and use it in GitHub Desktop.
This file contains 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.{ 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