Skip to content

Instantly share code, notes, and snippets.

@alexandredantas
Created July 29, 2019 17:17
Show Gist options
  • Save alexandredantas/eb5d205fbeb7a6ece837f4f1b9557d21 to your computer and use it in GitHub Desktop.
Save alexandredantas/eb5d205fbeb7a6ece837f4f1b9557d21 to your computer and use it in GitHub Desktop.
custom monads for tagless final
import scalaz.std.list._
import zio.IO
import scalaz.{ Applicative, Monad }
import scala.util.Try
package object types{
type ThrowableSafeResult[+T] = IO[Throwable, T]
implicit val ioMonadInstance: Monad[ThrowableSafeResult] = new Monad[ThrowableSafeResult] {
override def point[A](a: => A): ThrowableSafeResult[A] = IO.effectAsync { callback =>
Try {
a
}
.map(res => callback(IO.succeed(res)))
.recover { case error => callback(IO.fail(error)) }
}
override def bind[A, B](fa: ThrowableSafeResult[A])(f: A => ThrowableSafeResult[B]): ThrowableSafeResult[B] =
fa.flatMap(f)
}
implicit val ioApplicativeInstance: Applicative[ThrowableSafeResult] = new Applicative[ThrowableSafeResult] {
override def point[A](a: => A): ThrowableSafeResult[A] = IO.effectAsync { callback =>
Try {
a
}
.map(res => callback(IO.succeed(res)))
.recover { case error => callback(IO.fail(error)) }
}
override def ap[A, B](fa: => ThrowableSafeResult[A])(f: => ThrowableSafeResult[A => B]): ThrowableSafeResult[B] =
fa.flatMap(a => f.map(_ (a)))
}
implicit class IOMonadInstanceOps[F[_]](monad: Monad[F]) {
def flatLift[A, B](fn: A => F[B]): F[A] => F[B] = {
monad.bind(_)(fn)
}
def sequenceMap[A, B](xs: List[A])(fn: A => F[B]): F[List[B]] = {
monad.sequence(xs.map(fn))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment