From ccab783b3d1241cdf0d439633e042ad998309ad8 Mon Sep 17 00:00:00 2001 From: Patrick Oscar Boykin Date: Sun, 17 Sep 2023 12:15:34 -1000 Subject: [PATCH] factor ParallelViaProduct to possibly use elsewhere --- .../org/bykn/bosatsu/DefRecursionCheck.scala | 55 +++++++------------ .../org/bykn/bosatsu/ParallelViaProduct.scala | 31 +++++++++++ 2 files changed, 51 insertions(+), 35 deletions(-) create mode 100644 core/src/main/scala/org/bykn/bosatsu/ParallelViaProduct.scala diff --git a/core/src/main/scala/org/bykn/bosatsu/DefRecursionCheck.scala b/core/src/main/scala/org/bykn/bosatsu/DefRecursionCheck.scala index 5efaeacb8..a8c76e5c1 100644 --- a/core/src/main/scala/org/bykn/bosatsu/DefRecursionCheck.scala +++ b/core/src/main/scala/org/bykn/bosatsu/DefRecursionCheck.scala @@ -6,7 +6,6 @@ import org.typelevel.paiges.Doc import cats.implicits._ import Identifier.Bindable -import cats.Applicative /** * Recursion in bosatsu is only allowed on a substructural match @@ -268,44 +267,30 @@ object DefRecursionCheck { implicit val parallelSt: cats.Parallel[St] = { val m = cats.Monad[St] - new cats.Parallel[St] { - type F[A] = St[A] - def parallel = new cats.arrow.FunctionK[St, F] { - def apply[A](st: St[A]) = st - } - def sequential = new cats.arrow.FunctionK[F, St] { - def apply[A](st: St[A]) = st - } + new ParallelViaProduct[St] { def monad = m - def applicative: Applicative[F] = - new Applicative[F] { - def pure[A](a: A) = m.pure(a) - def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = - map(product(ff, fa)) { case (fn, a) => fn(a) } - - override def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] = { - type E[+X] = Either[NonEmptyList[RecursionError], X] - val fna: E[State => E[(State, A)]] = fa.runF - val fnb: E[State => E[(State, B)]] = fb.runF - - new cats.data.IndexedStateT((fna, fnb).parMapN { (fn1, fn2) => - { (state: State) => - fn1(state) match { - case Right((s2, a)) => fn2(s2).map { case (st, b) => (st, (a, b)) } - case Left(nel1) => - // just skip and merge - fn2(state) match { - case Right(_) => Left(nel1) - case Left(nel2) => Left(nel1 ::: nel2) - } + def parallelProduct[A, B](fa: St[A], fb: St[B]) = { + type E[+X] = Either[NonEmptyList[RecursionError], X] + val fna: E[State => E[(State, A)]] = fa.runF + val fnb: E[State => E[(State, B)]] = fb.runF + + new cats.data.IndexedStateT((fna, fnb).parMapN { (fn1, fn2) => + { (state: State) => + fn1(state) match { + case Right((s2, a)) => fn2(s2).map { case (st, b) => (st, (a, b)) } + case Left(nel1) => + // just skip and merge + fn2(state) match { + case Right(_) => Left(nel1) + case Left(nel2) => Left(nel1 ::: nel2) } - } - }) - } - override def map[A, B](fa: F[A])(fn: A => B) = m.map(fa)(fn) - } + } + } + }) + } } } + // Scala has trouble infering types like St, we we make these typed // helper functions to use below def failSt[A](err: RecursionError): St[A] = diff --git a/core/src/main/scala/org/bykn/bosatsu/ParallelViaProduct.scala b/core/src/main/scala/org/bykn/bosatsu/ParallelViaProduct.scala new file mode 100644 index 000000000..0d9e65f11 --- /dev/null +++ b/core/src/main/scala/org/bykn/bosatsu/ParallelViaProduct.scala @@ -0,0 +1,31 @@ +package org.bykn.bosatsu + +import cats.arrow.FunctionK +import cats.{Parallel, Applicative} + +// Implement Parallel by implementing just Product +abstract class ParallelViaProduct[G[_]] extends Parallel[G] { self => + + type F[A] = G[A] + val parallel = new FunctionK[G, F] { + def apply[A](ga: G[A]) = ga + } + + val sequential = new FunctionK[F, G] { + def apply[A](fa: F[A]) = fa + } + + def parallelProduct[A, B](fa: F[A], fb: F[B]): F[(A, B)] + + val applicative: Applicative[F] = + new Applicative[F] { self => + def pure[A](a: A) = monad.pure(a) + + final def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = + monad.map(parallelProduct(ff, fa)) { case (fn, a) => fn(a) } + + override def map[A, B](fa: F[A])(fn: A => B) = monad.map(fa)(fn) + + override def product[A, B](fa: F[A], fb: F[B]) = parallelProduct(fa, fb) + } +} \ No newline at end of file