Last active
October 21, 2021 14:48
-
-
Save programaker/b9246c4e2e8e40a519986765d2ab316f to your computer and use it in GitHub Desktop.
Today Traverse was not the answer; it was Foldable
This file contains hidden or 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.effect.IO | |
import cats.syntax.foldable._ | |
import cats.syntax.applicative._ | |
import cats.syntax.applicativeError._ | |
import cats.{ApplicativeThrow, Monad} | |
import scala.util.Try | |
// Stores type aliases for effects that have more then one type parameter | |
object Fs { | |
type Either_[A] = Either[Throwable, A] | |
} | |
import Fs._ | |
/// | |
trait Interpreter[F[_]] { | |
def run[A](fa: F[A]): A | |
} | |
object Interpreter { | |
def apply[F[_]](implicit I: Interpreter[F]): Interpreter[F] = I | |
implicit val eitherInterpreter: Interpreter[Either_] = new Interpreter[Either_] { | |
override def run[A](fa: Either_[A]): A = fa match { | |
case Left(e) => throw e | |
case Right(a) => a | |
} | |
} | |
import cats.effect.unsafe.implicits.global | |
implicit val ioInterpreter: Interpreter[IO] = new Interpreter[IO] { | |
override def run[A](fa: IO[A]): A = fa.unsafeRunSync() | |
} | |
implicit val tryInterpreter: Interpreter[Try] = new Interpreter[Try] { | |
override def run[A](fa: Try[A]): A = fa.get | |
} | |
} | |
implicit class InterpreterSyntax[F[_]: Interpreter, A](fa: F[A]) { | |
def run(): A = Interpreter[F].run(fa) | |
} | |
/// | |
final case class Frunfles(value: String) | |
val goodList = List( | |
Frunfles("A"), | |
Frunfles("B"), | |
Frunfles("C"), | |
Frunfles("X"), | |
Frunfles("Y"), | |
Frunfles("Z"), | |
) | |
val badList = List( | |
Frunfles("A"), | |
Frunfles("B"), | |
Frunfles("C"), | |
Frunfles(""), //<- a bad Frunfles among us! | |
Frunfles("X"), | |
Frunfles("Y"), | |
Frunfles("Z"), | |
) | |
/// | |
def doStuff[F[_]: Monad](value: String, version: Int): F[Int] = { | |
// pretend I'm doing something with the `value` | |
// and returning an updated version | |
(version + 1).pure | |
} | |
def f[F[_]: Monad: ApplicativeThrow](allFrunfles: List[Frunfles], startVersion: Int): F[Int] = { | |
// `foldLeftM` works with any `F[_]` as long as a `Monad` instance exists for it! =D | |
// It breaks the folding loop if an error happens - if the Monad instance has some "error" semantic | |
allFrunfles.foldLeftM(startVersion) { (version, frunfles) => | |
if (frunfles.value.isBlank) { | |
println(">>> <blank>") | |
new IllegalStateException("Frunfles must have a value").raiseError | |
} else { | |
println(s">>> ${frunfles.value}") | |
doStuff(frunfles.value, version) | |
} | |
} | |
} | |
/// | |
// Change the effect and the list in `f[...]` | |
val out = f[IO](badList, 1).run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment