Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
blog-201706.scala
sealed trait Field {
type Value
def fold[F[_]](f: Field.Fold[F]): F[Value]
}
object Field {
case object Name extends Field {
override type Value = String
override def fold[F[_]](f: Field.Fold[F]): F[Value] = f.name(this)
}
case object Age extends Field {
override type Value = Int
override def fold[F[_]](f: Field.Fold[F]): F[Value] = f.age(this)
}
final case class Fold[F[_]](name: Field.Name.type => F[Field.Name.Value],
age : Field.Age .type => F[Field.Age .Value]) {
def apply(f: Field): F[f.Value] =
f.fold(this)
}
}
object Examples {
type GetValue[Value] = Value
val getValue = Field.Fold[GetValue](
name = _ => "Hello",
age = _ => 99)
type Print[Value] = Value => Unit
val printValue = Field.Fold[Print](
name = _ => n => println(s"My name is $n."),
age = _ => i => println(s"I am $i years old."))
type Validate[Value] = Value => Either[String, Value]
val validateName: Validate[String] =
name => {
val name2 = name.trim
if (name2.isEmpty) Left("Name can't be empty") else Right(name2)
}
val validateAge: Validate[Int] =
a => if (a >= 0 && a <= 150) Right(a) else Left("Your age is bullshit")
val validate = Field.Fold[Validate](
name = _ => validateName,
age = _ => validateAge)
val f = Field.Name
val v = getValue(f)
printValue(f)(v)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment