From 1626cc3d635fcab41daa9b0dc560bd7fc48362c6 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Mon, 10 Feb 2025 09:33:04 -0500 Subject: [PATCH] Configured: add flatten etc. --- .../main/scala/metaconfig/Configured.scala | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/metaconfig-core/shared/src/main/scala/metaconfig/Configured.scala b/metaconfig-core/shared/src/main/scala/metaconfig/Configured.scala index 2b7350c..27267a3 100644 --- a/metaconfig-core/shared/src/main/scala/metaconfig/Configured.scala +++ b/metaconfig-core/shared/src/main/scala/metaconfig/Configured.scala @@ -3,12 +3,13 @@ package metaconfig import scala.language.implicitConversions import scala.util.Failure import scala.util.Success +import scala.util.Try sealed abstract class Configured[+A] extends Product with Serializable { import Configured._ def getOrElse[B >: A](els: => B): B = this match { case Ok(value) => value - case NotOk(_) => els + case _: NotOk => els } def get: A = this match { case Ok(value) => value @@ -30,18 +31,22 @@ sealed abstract class Configured[+A] extends Product with Serializable { } def map[B](f: A => B): Configured[B] = this match { case Ok(value) => Ok(f(value)) - case x @ NotOk(_) => x + case x: NotOk => x } def |@|[B](other: Configured[B]): Configured[(A, B)] = this.product(other) def product[B](other: Configured[B]): Configured[(A, B)] = (this, other) match { case (Ok(a), Ok(b)) => Ok(a -> b) case (a: NotOk, b: NotOk) => a.combine(b) - case (NotOk(_), _) => this.asInstanceOf[Configured[(A, B)]] - case (_, NotOk(_)) => other.asInstanceOf[Configured[(A, B)]] + case (_: NotOk, _) => this.asInstanceOf[Configured[(A, B)]] + case (_, _: NotOk) => other.asInstanceOf[Configured[(A, B)]] } def andThen[B](f: A => Configured[B]): Configured[B] = this match { case Ok(value) => f(value) - case x @ NotOk(_) => x + case x: NotOk => x + } + def andThenTry[B](f: A => Configured[B]): Configured[B] = this match { + case Ok(value) => fromExceptionThrowingFlatten(f(value)) + case x: NotOk => x } def isOk: Boolean = this match { case Ok(_) => true; case _ => false } def isNotOk: Boolean = !isOk @@ -51,7 +56,7 @@ trait ConfiguredLowPriorityImplicits { // implicit def toOption[A](value: Configured[A]): Option[A] = // value match { - // case Configured.Ok(v) => Some(v) + // case Ok(v) => Some(v) // case _ => None // } @@ -75,11 +80,15 @@ object Configured extends ConfiguredLowPriorityImplicits { def notOk[T](error: ConfError): Configured[T] = NotOk(error) def error(message: String): Configured[Nothing] = ConfError.message(message) .notOk - def fromExceptionThrowing[T](thunk: => T): Configured[T] = scala.util - .Try(thunk) match { - case Failure(exception) => Configured.exception(exception) - case Success(value) => Configured.ok(value) + def fromExceptionThrowing[T](thunk: => T): Configured[T] = Try(thunk) match { + case Failure(v) => exception(v) + case Success(v) => Ok(v) } + def fromExceptionThrowingFlatten[T](thunk: => Configured[T]): Configured[T] = + Try(thunk) match { + case Failure(v) => exception(v) + case Success(v) => v + } def exception( exception: Throwable, stackSize: Int = 10, @@ -95,16 +104,15 @@ object Configured extends ConfiguredLowPriorityImplicits { def combine(other: NotOk): NotOk = combine(other.error) } - implicit def errorToNotOK(error: ConfError): Configured.NotOk = Configured - .NotOk(error) + implicit def errorToNotOK(error: ConfError): NotOk = NotOk(error) implicit class ConfiguredImplicit[A](value: Configured[A]) { def getOrRecover(fa: ConfError => A): A = fold(fa)(identity) def fold[B](fa: ConfError => B)(fb: A => B): B = value match { - case Configured.Ok(value) => fb(value) - case Configured.NotOk(error) => fa(error) + case Ok(value) => fb(value) + case NotOk(error) => fa(error) } def foreach(fa: ConfError => Unit)(fb: A => Unit): Unit = fold(fa)(fb) @@ -113,8 +121,17 @@ object Configured extends ConfiguredLowPriorityImplicits { .recoverWith(x => f.recoverWith(x.combine)) def getError: ConfError = value match { - case Configured.Ok(value) => ConfError.message(s"Not an error: $value") - case Configured.NotOk(error) => error + case Ok(value) => ConfError.message(s"Not an error: $value") + case NotOk(error) => error + } + + } + + implicit class ConfiguredConfiguredImplicit[A](value: Configured[Configured[A]]) { + + def flatten: Configured[A] = value match { + case Ok(v) => v + case v: NotOk => v } }