Skip to content

Instantly share code, notes, and snippets.

@japgolly
Created June 5, 2017 10:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save japgolly/162f102d516abf86b54359ef0b1d3b65 to your computer and use it in GitHub Desktop.
Save japgolly/162f102d516abf86b54359ef0b1d3b65 to your computer and use it in GitHub Desktop.
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