Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Freestyle Effects for @tagless #507

Merged
merged 9 commits into from
Jan 12, 2018
28 changes: 8 additions & 20 deletions modules/effects/shared/src/main/scala/free/effects/either.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,28 @@
package freestyle.free
package effects

import cats.{Eval, MonadError}
import scala.util.control.NonFatal

object either {

final class ErrorProvider[E] {

@free sealed trait EitherM {
def either[A](fa: Either[E, A]): FS[A]
def error[A](e: E): FS[A]
def catchNonFatal[A](a: Eval[A], f: Throwable => E): FS[A]
}
val taglessV: freestyle.tagless.effects.either.ErrorProvider[E] = freestyle.tagless.effects.either[E]

trait Implicits {
implicit def freeStyleEitherMHandler[M[_]](
implicit ME: MonadError[M, E]): EitherM.Handler[M] = new EitherM.Handler[M] {
def either[A](fa: Either[E, A]): M[A] = fa.fold(ME.raiseError[A], ME.pure[A])
def error[A](e: E): M[A] = ME.raiseError[A](e)
def catchNonFatal[A](a: Eval[A], f: Throwable => E): M[A] =
try ME.pure(a.value)
catch {
case NonFatal(e) => ME.raiseError(f(e))
}
}
type EitherM[F[_]] = taglessV.EitherM.StackSafe[F]

val EitherM = taglessV.EitherM.StackSafe

trait FreeImplicits extends taglessV.Implicits {

class EitherFreeSLift[F[_]: EitherM] extends FreeSLift[F, Either[E, ?]] {
def liftFSPar[A](fa: Either[E, A]): FreeS.Par[F, A] = EitherM[F].either(fa)
}

implicit def freeSLiftEither[F[_]: EitherM]: FreeSLift[F, Either[E, ?]] =
new EitherFreeSLift[F]

}

object implicits extends Implicits
object implicits extends FreeImplicits
}

def apply[E]: ErrorProvider[E] = new ErrorProvider
Expand Down
19 changes: 4 additions & 15 deletions modules/effects/shared/src/main/scala/free/effects/error.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,13 @@
package freestyle.free
package effects

import cats.{Eval, MonadError}

object error {

@free sealed trait ErrorM {
def either[A](fa: Either[Throwable, A]): FS[A]
def error[A](e: Throwable): FS[A]
def catchNonFatal[A](a: Eval[A]): FS[A]
}
type ErrorM[F[_]] = freestyle.tagless.effects.error.ErrorM.StackSafe[F]

trait Implicits {
val ErrorM = freestyle.tagless.effects.error.ErrorM.StackSafe

implicit def freeStyleErrorMHandler[M[_]](
implicit ME: MonadError[M, Throwable]): ErrorM.Handler[M] = new ErrorM.Handler[M] {
def either[A](fa: Either[Throwable, A]): M[A] = fa.fold(ME.raiseError[A], ME.pure[A])
def error[A](e: Throwable): M[A] = ME.raiseError[A](e)
def catchNonFatal[A](a: Eval[A]): M[A] = ME.catchNonFatal[A](a.value)
}
trait FreeImplicits extends freestyle.tagless.effects.error.Implicits {

class ErrorFreeSLift[F[_]: ErrorM] extends FreeSLift[F, Either[Throwable, ?]] {
def liftFSPar[A](fa: Either[Throwable, A]): FreeS.Par[F, A] = ErrorM[F].either(fa)
Expand All @@ -45,5 +34,5 @@ object error {

}

object implicits extends Implicits
object implicits extends FreeImplicits
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
package freestyle.free
package effects

object implicits extends option.Implicits with error.Implicits
object implicits extends option.FreeImplicits with error.FreeImplicits
20 changes: 5 additions & 15 deletions modules/effects/shared/src/main/scala/free/effects/option.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,13 @@
package freestyle.free
package effects

import cats.Applicative
import cats.mtl.FunctorEmpty

object option {

@free sealed trait OptionM {
def option[A](fa: Option[A]): FS[A]
def none[A]: FS[A]
}
type OptionM[F[_]] = freestyle.tagless.effects.option.OptionM.StackSafe[F]

val OptionM = freestyle.tagless.effects.option.OptionM.StackSafe

trait Implicits {
implicit def freeStyleOptionMHandler[M[_]](
implicit FE: FunctorEmpty[M], A: Applicative[M]): OptionM.Handler[M] =
new OptionM.Handler[M] {
def option[A](fa: Option[A]): M[A] = FE.flattenOption(A.pure(fa))
def none[A]: M[A] = option(Option.empty[A])
}
trait FreeImplicits extends freestyle.tagless.effects.option.Implicits {

class OptionFreeSLift[F[_]: OptionM] extends FreeSLift[F, Option] {
def liftFSPar[A](fa: Option[A]): FreeS.Par[F, A] = OptionM[F].option(fa)
Expand All @@ -42,5 +32,5 @@ object option {
implicit def freeSLiftOption[F[_]: OptionM]: FreeSLift[F, Option] = new OptionFreeSLift[F]
}

object implicits extends Implicits
object implicits extends FreeImplicits
}
21 changes: 6 additions & 15 deletions modules/effects/shared/src/main/scala/free/effects/reader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,19 @@
package freestyle.free
package effects

import cats.mtl.ApplicativeAsk

object reader {

final class EnvironmentProvider[R] {

@free abstract class ReaderM {
def ask: FS[R]
def reader[B](f: R => B): FS[B]
}
val taglessV: freestyle.tagless.effects.reader.EnvironmentProvider[R] =
freestyle.tagless.effects.reader[R]

type ReaderM[F[_]] = taglessV.ReaderM.StackSafe[F]

trait Implicits {
val ReaderM = taglessV.ReaderM.StackSafe

implicit def freestyleReaderMHandler[M[_]](
implicit AL: ApplicativeAsk[M, R]): ReaderM.Handler[M] =
new ReaderM.Handler[M] {
def ask: M[R] = AL.ask
def reader[B](f: R => B): M[B] = AL.reader(f)
}
}
object implicits extends taglessV.Implicits

object implicits extends Implicits
}

def apply[R] = new EnvironmentProvider[R]
Expand Down
25 changes: 8 additions & 17 deletions modules/effects/shared/src/main/scala/free/effects/state.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,18 @@
package freestyle.free
package effects

import cats.mtl.MonadState

object state {

final class StateSeedProvider[S] {

@free sealed abstract class StateM {
def get: FS[S]
def set(s: S): FS[Unit]
def modify(f: S => S): FS[Unit]
def inspect[A](f: S => A): FS[A]
}
val taglessV: freestyle.tagless.effects.state.StateSeedProvider[S] =
freestyle.tagless.effects.state[S]

trait Implicits {
type StateM[F[_]] = taglessV.StateM.StackSafe[F]

implicit def freestyleStateMHandler[M[_]](implicit MS: MonadState[M, S]): StateM.Handler[M] =
new StateM.Handler[M] {
def get: M[S] = MS.get
def set(s: S): M[Unit] = MS.set(s)
def modify(f: S => S): M[Unit] = MS.modify(f)
def inspect[A](f: S => A): M[A] = MS.inspect(f)
}
val StateM = taglessV.StateM.StackSafe

trait FreeImplicits extends taglessV.Implicits {

class StateInspectFreeSLift[F[_]: StateM] extends FreeSLift[F, Function1[S, ?]] {
def liftFSPar[A](fa: S => A): FreeS.Par[F, A] = StateM[F].inspect(fa)
Expand All @@ -49,7 +39,8 @@ object state {

}

object implicits extends Implicits
object implicits extends FreeImplicits

}

def apply[S] = new StateSeedProvider[S]
Expand Down
41 changes: 15 additions & 26 deletions modules/effects/shared/src/main/scala/free/effects/traverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,30 @@
package freestyle.free
package effects

import cats.{~>, Alternative, Foldable, Monad}

object traverse {

final class TraverseProvider[G[_]] {

/** Acts as a generator providing traversable semantics to programs
*/
@free sealed abstract class TraverseM {
def empty[A]: FS[A]
def fromTraversable[A](ta: G[A]): FS[A]
}
val taglessV: freestyle.tagless.effects.traverse.TraverseProvider[G] =
freestyle.tagless.effects.traverse[G]

/** Interpretable as long as a `Foldable` instance for G[_] and a `Monad` and
* an `Alternative` instnace for M[_] exists in scope.
*/
trait Implicits {
implicit def freestyleTraverseMHandler[F[_], M[_]](
implicit M: Monad[M],
MA: Alternative[M],
FT: Foldable[G]): TraverseM.Handler[M] =
new TraverseM.Handler[M] {
def empty[A]: M[A] = MA.empty[A]
def fromTraversable[A](ta: G[A]): M[A] = FT.foldMap(ta)(MA.pure)(MA.algebra[A])
}
}
type TraverseM[F[_]] = taglessV.TraverseM.StackSafe[F]

val TraverseM = taglessV.TraverseM.StackSafe

trait FreeImplicits extends taglessV.Implicits {

class TraverseFreeSLift[F[_]: TraverseM] extends FreeSLift[F, G] {
def liftFSPar[A](fa: G[A]): FreeS.Par[F, A] = TraverseM[F].fromTraversable(fa)
}

implicit def freeSLiftTraverse[F[_]: TraverseM]: FreeSLift[F, G] =
new TraverseFreeSLift[F]

class TraverseFreeSLift[F[_]: TraverseM] extends FreeSLift[F, G] {
def liftFSPar[A](fa: G[A]): FreeS.Par[F, A] = TraverseM[F].fromTraversable(fa)
}

implicit def freeSLiftTraverse[F[_]: TraverseM]: FreeSLift[F, G] =
new TraverseFreeSLift[F]
object implicits extends FreeImplicits

object implicits extends Implicits
}

def apply[T[_]] = new TraverseProvider[T]
Expand Down
55 changes: 13 additions & 42 deletions modules/effects/shared/src/main/scala/free/effects/validation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,59 +17,30 @@
package freestyle.free
package effects

import cats.data.{NonEmptyList, State, Validated, ValidatedNel}
import cats.mtl.MonadState

object validation {
final class ValidationProvider[E] {
type Errors = List[E]

/** An algebra for introducing validation semantics in a program. **/
@free sealed trait ValidationM {
def valid[A](x: A): FS[A]

def invalid(err: E): FS[Unit]

def errors: FS[Errors]

def fromEither[A](x: Either[E, A]): FS[Either[E, A]]

def fromValidatedNel[A](x: ValidatedNel[E, A]): FS[ValidatedNel[E, A]]
}

trait Implicits {
implicit def freeStyleValidationMStateInterpreter[M[_]](
implicit MS: MonadState[M, Errors]
): ValidationM.Handler[M] = new ValidationM.Handler[M] {
def valid[A](x: A): M[A] = MS.monad.pure(x)
final class ValidationProvider[E] {

def errors: M[Errors] = MS.get
val taglessV: freestyle.tagless.effects.validation.ValidationProvider[E] =
freestyle.tagless.effects.validation[E]

def invalid(err: E): M[Unit] = MS.modify((s: Errors) => s :+ err)
type ValidationM[F[_]] = taglessV.ValidationM.StackSafe[F]

def fromEither[A](x: Either[E, A]): M[Either[E, A]] =
x match {
case Left(err) => MS.monad.as(invalid(err), x)
case Right(_) => MS.monad.pure(x)
}
val ValidationM = taglessV.ValidationM.StackSafe

def fromValidatedNel[A](x: ValidatedNel[E, A]): M[ValidatedNel[E, A]] =
x match {
case Validated.Invalid(errs) =>
MS.monad.as(MS.modify((s: Errors) => s ++ errs.toList), x)
case Validated.Valid(_) => MS.monad.pure(x)
}
}
trait FreeImplicits extends taglessV.Implicits {

implicit class ValidSyntax[A](private val s: A) {
def liftValid[F[_]: ValidationM]: FreeS[F, A] = ValidationM[F].valid(s)
implicit class FreeValidSyntax[A](private val s: A) {
def liftValid[F[_]: ValidationM] = ValidationM[F].valid(s)
}
implicit class InvalidSyntax[A](private val e: E) {
def liftInvalid[F[_]: ValidationM]: FreeS[F, Unit] = ValidationM[F].invalid(e)
implicit class FreeInvalidSyntax[A](private val e: E) {
def liftInvalid[F[_]: ValidationM] = ValidationM[F].invalid(e)
}

}

object implicits extends Implicits
object implicits extends FreeImplicits

}

def apply[E] = new ValidationProvider[E]
Expand Down
23 changes: 6 additions & 17 deletions modules/effects/shared/src/main/scala/free/effects/writer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,18 @@
package freestyle.free
package effects

import cats.mtl.FunctorTell

object writer {

final class AccumulatorProvider[W] {

@free sealed abstract class WriterM {
def writer[A](aw: (W, A)): FS[A]
def tell(w: W): FS[Unit]
}
final class AccumulatorProvider[E] {

trait Implicits {
val taglessV: freestyle.tagless.effects.writer.AccumulatorProvider[E] =
freestyle.tagless.effects.writer[E]

implicit def freestyleWriterMHandler[M[_]](
implicit FT: FunctorTell[M, W]): WriterM.Handler[M] =
new WriterM.Handler[M] {
def writer[A](aw: (W, A)): M[A] = FT.tuple(aw)
def tell(w: W): M[Unit] = FT.tell(w)
}
type WriterM[F[_]] = taglessV.WriterM.StackSafe[F]

}
val WriterM = taglessV.WriterM.StackSafe

object implicits extends Implicits
object implicits extends taglessV.Implicits
}

def apply[W] = new AccumulatorProvider[W]
Expand Down
Loading