Share
Embed
Transcript
22 slides
-
நԽ def authF(name: String, password: String): Future[User] def authT(name: String,
password: String): Try[User] def authE(name: String, password: String): Either[String, User] def auth[F[_]](name: String, password: String): F[User] 5BHMFTT'JOBMͰ ྑ͘ग़ͯ͘Δͭ -
ΤϥʔϋϯυϦϯά 'VUVSF &JUIFS 5SZ Τϥʔʹର͢Δॲཧ Future { ??? throw new
RuntimeException } recoverWith { case e: IllegalArgumentException => Future.successful(0) } Try { ??? throw new RuntimeException } match { case Success(result) => result case Failure(e) => println(s"failure :${e.getMessage}") } Either { ??? Left("Error") } match { case Right(success) => success case Left(e) => println(s"failure: $e") } -
.POBEͰநԽ͕͍͠ྫ 'VUVSF &JUIFS 5SZ def program(value: Either[String, Int], e: =>
String): Either[String, Int] = for { n <- value result <- if(n < 0) Left(e) else Right(n * 2) } yield result def program(value: Future[Int], e: => String)(implicit ec: ExecutionContext): Future[Int] = for { n <- value result <- if(n < 0) Future.failed(new RuntimeException(e)) else Future.successful(n*2) } yield result def program(value: Try[Int], e: => String): Try[Int] = for { n <- value result <- if(n < 0) Failure(new RuntimeException(e)) else Success(n*2) } yield result -
'VUVSF &JUIFS 5SZ def program(value: Either[String, Int], e: => String):
Either[String, Int] = for { n <- value result <- if(n < 0) Left(e) else Right(n * 2) } yield result .POBEʹΑͬͯ ΤϥʔϋϯυϦϯά ͕ҟͳΔ .POBEͰநԽ͕͍͠ྫ def program(value: Future[Int], e: => String)(implicit ec: ExecutionContext): Future[Int] = for { n <- value result <- if(n < 0) Future.failed(new RuntimeException(e)) else Future.successful(n*2) } yield result def program(value: Try[Int], e: => String): Try[Int] = for { n <- value result <- if(n < 0) Failure(new RuntimeException(e)) else Success(n*2) } yield result -
Ϟνϕʔγϣϯ def program[F[_], E](value: F[Int], e: => E)(implicit ME: MonadError[F,
E]): F[Int] def program(value: Either[String, Int], e: => String): Either[String, Int] def program(value: Future[Int], e: => String)(implicit ec: ExecutionContext): Future[Int] def program(value: Try[Int], e: => String): Try[Int] -
.POBE&SSPSJODBUT trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] {
def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A] def raiseError[A](e: E): F[A] def handleError[A](fa: F[A])(f: E => A): F[A] … } .POBEͷܕ 'ʹؚ·ΕΔ Τϥʔͷܕ .POBEΛܧঝ -
QVSF def pure[A](x: A): F[A] "Λ'<">ʹ্࣋ͪ͛Δ.POBEͰ͓ͳ͡Έͷؔ def pure[B](b: B): Either[A,
B] = Right(b) 'VUVSF &JUIFS def pure[A](x: A): Future[A] = Future.successful(x) -
SBJTF&SSPS ΤϥʔͷதΛ'<@>ʹ্࣋ͪ͛Δ def raiseError[A](e: E): F[A] def raiseError[B](e: A): Either[A,
B] = Left(e) def raiseError[A](e: Throwable): Future[A] = Future.failed(e) 'VUVSF &JUIFS -
IBOEMF&SSPS def handleError[A](fa: F[A])(f: E => A): F[A] ΤϥʔΛͬͯޭʹม͢Δɻ 'VUVSFͷSFDPWFS8JUIΈ͍ͨͳͭ
monadError.handleError(value) { case failure: E => "It's Ok" } override def handleError[A](fea: Future[A])(f: Throwable => A): Future[A] = fea.recover { case t => f(t) } 'VUVSF def handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A] monadError.handleErrorWith(value) { case failure: E => monadError.pure("It's Ok") case _ => monadError.raiseError(failure) } -
FOTVSF def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A]
MonadError[({type E[A] = Either[String, A]})#E, String].ensure(Right(42))("Error")(_ > 0) // Right(42) MonadError[({type E[A] = Either[String, A]})#E, String].ensure(Right(-42))(“Error”)(_ > 0) // Left(Error) def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A] = flatMap(fa)(a => if (predicate(a)) pure(a) else raiseError(error)) ݅ࣜ QSFEJDBUF Λ͔͚ͯɺ USVFͳΒޭɺGBMTFͳΒΤϥʔ FSSPS Λฦؔ͢ -
Ϟνϕʔγϣϯ def program[F[_], E](value: F[Int], e: => E)(implicit ME: MonadError[F,
E]): F[Int] def program(value: Either[String, Int], e: => String): Either[String, Int] def program(value: Future[Int], e: => String)(implicit ec: ExecutionContext): Future[Int] def program(value: Try[Int], e: => String): Try[Int] -
.POBE&SSPSʹΑΔநԽ ΤϥʔॲཧΛநԽ trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F]
{ def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A] = flatMap(fa)(a => if (predicate(a)) pure(a) else raiseError(error)) } ؆ܿͳදݱ͕Մೳ def program(value: Either[String, Int], e: => String): Either[String, Int] = for { n <- value result <- if(n < 0) Left(e) else Right(n * 2) } yield result def program[F[_], E](value: F[Int], e: => E)(implicit monadError: MonadError[F, E]): F[Int] = for { n <- value result <- if(n < 0) monadError.raiseError(e) else monadError.pure(n * 2) } yield result def program[F[_], E](value: F[Int], e: => E)(implicit monadError: MonadError[F, E]): F[Int] = monadError.ensure(value)(e)(_ >= 0).map(_*2) -
͏ଆ.POBE&SSPSͷ࣮Λࠩ͠ࠐΉ // MonadErrorͷEitherͷ࣮ implicit val monadErrorForEither = new MonadError[Either[String, Int],
String] { ??? } val resEitherSuccess = program[({type E[A] = Either[String, A]})#E, String](43.asRight[String], "Error") // Right(86) val resEitherFailure = program[({type E[A] = Either[String, A]})#E, String](-43.asRight[String], "Error") // Left("Error") .POBE&SSPSʹΑΔநԽ def program[F[_], E](value: F[Int], e: => E)(implicit monadError: MonadError[F, E]): F[Int] = monadError.ensure(value)(e)(_ >= 0).map(_*2) -
new MonadError[Either[A, ?], A] with Traverse[Either[A, ?]] { def pure[B](b:
B): Either[A, B] = Right(b) def flatMap[B, C](fa: Either[A, B])(f: B => Either[A, C]): Either[A, C] = fa.right.flatMap(f) def raiseError[B](e: A): Either[A, B] = Left(e) … } new FutureCoflatMap with MonadError[Future, Throwable] with Monad[Future] with StackSafeMonad[Future] { def pure[A](x: A): Future[A] = Future.successful(x) def flatMap[A, B](fa: Future[A])(f: A => Future[B]): Future[B] = fa.flatMap(f) def raiseError[A](e: Throwable): Future[A] = Future.failed(e) … } 'VUVSF &JUIFS 5SZ 'VUVSF &JUIFS 0QUJPO *0ͷ࣮͕طʹ͋Δ .POBE&SSPS*OTUBODFJODBUT -
ͦΕͧΕͷ.POBE&SSPSͷ࣮Λࠩ͠ࠐΉ͚ͩ import cats.instances.try_._ val resTrySuccess = program[Try, Throwable](Success(43), new RuntimeException(“Error"))
// = Success(43) val resTryFailure = program[Try, Throwable](Success(-43), new RuntimeException("Error")) // = Failure(RuntimeException("Error")) import cats.instances.future._ val resFutureSuccess = program[Future, Throwable](Future(43), new RuntimeException(“Error")) // = onComplete => Success(43) val resFutureFailure = program[Future, Throwable](Future(-43), new RuntimeException(“Error")) // = onComplete => Failure(RuntimeException("Error")) 'VUVSF &JUIFS 5SZ import cats.syntax.either._ import cats.instances.either._ val resEitherSuccess = program[({type E[A] = Either[String, A]})#E, String](43.asRight[String], "Error") // Right(86) val resEitherFailure = program[({type E[A] = Either[String, A]})#E, String](-43.asRight[String], "Error") // Left("Error") def program[F[_], E](value: F[Int], e: => E)(implicit ME: MonadError[F, E]): F[Int] = ME.ensure(value)(e)(_ >= 0).map(_*2) .POBE&SSPS*OTUBODFJODBUT