Last active
September 26, 2022 16:50
-
-
Save sshark/664eaa2cc64004ead0a5565fc6b7c480 to your computer and use it in GitHub Desktop.
This file contains 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
case class Config(name: String, age: Int) | |
case class Name(firstName: String, lastName: String) | |
case class Age(age: Int) extends AnyVal | |
case class Person(name: Name, age: Age) | |
object Configs: | |
type Configured[T] = Config ?=> T | |
def config: Configured[Config] = summon[Config] | |
object Exceptions: | |
private class E extends Exception | |
class CanThrow private[Exceptions](): | |
private[Exceptions] def throwE() = throw new E | |
type Possibly[T] = CanThrow ?=> T | |
def require(p: Boolean)(using ct: CanThrow):Unit = if (!p) ct.throwE() | |
def attempt[T](op: Possibly[T]) = new OnError(op) | |
class OnError[T](op: Possibly[T]): | |
def onError(fallback: => T): T = | |
try op(using new CanThrow) | |
catch | |
case ex: E => fallback | |
import Configs.* | |
import Exceptions.* | |
def readName: Possibly[Configured[Name]] = | |
val parts = config.name.split(" ") | |
require(parts.length >= 2) | |
Name(parts(0), parts.tail.mkString) | |
def readAge: Configured[Possibly[Age]] = | |
val age = config.age | |
require(1 <= age && age <= 150) | |
Age(age) | |
// Note: readName & readAge can only be invoked in attempt | |
// because of Context Functions i.e. Algebraic Effect | |
def readPerson: Configured[Option[Person]] = | |
attempt(Some(Person(readName, readAge))).onError(None) | |
println(readPerson(using Config("John Doe", 20))) | |
println(readPerson(using Config("Incognito", 99))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment