Skip to content

Instantly share code, notes, and snippets.

@sshark
Last active September 26, 2022 16:50
Show Gist options
  • Save sshark/664eaa2cc64004ead0a5565fc6b7c480 to your computer and use it in GitHub Desktop.
Save sshark/664eaa2cc64004ead0a5565fc6b7c480 to your computer and use it in GitHub Desktop.
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