Skip to content

Instantly share code, notes, and snippets.

@kkismd
Forked from gakuzzzz/enum.scala
Last active August 29, 2015 14:19
Show Gist options
  • Save kkismd/a8f6e98c5422b8597074 to your computer and use it in GitHub Desktop.
Save kkismd/a8f6e98c5422b8597074 to your computer and use it in GitHub Desktop.
trait AtomWrapper {
type ValueType
def value: ValueType
}
trait StringAtomWrapper extends AtomWrapper {
type ValueType = String
override def toString = value
}
trait IntAtomWrapper extends AtomWrapper {
type ValueType = Int
override def toString = value.toString
}
trait AtomCompanion[A <: AtomWrapper] {
def apply(value: A#ValueType): A
implicit val companion: AtomCompanion[A] = this
// この辺は各自適切なパッケージに切り出すなりお好きに
implicit def optionalTypeBinder(implicit ev: TypeBinder[Option[A#ValueType]]): TypeBinder[Option[A]] = ???
implicit def queryStringBindable(implicit ev: QueryStringBindable[A#ValueType]): QueryStringBindable[A] = ???
implicit def pathBindable(implicit ev: PathBindable[A#ValueType]): PathBindable[A] = ???
implicit def formatter(implicit ev: Formatter[A#ValueType]): Formatter[A] = ???
implicit def jsonFormat(implicit ev: Format[A#ValueType]): Format[A] = ???
}
case class UserId(value: Int) extends IntAtomWrapper
object UserId extends AtomCompanion[UserId]
type Database = Map[String, Any]
case class Item[+A](name: String) {
def get(d: Database) = d(name).asInstanceOf[A]
}
implicit class DB(val d: Database) extends AnyVal {
def get[A](n: Item[A]): A = n.get(d)
}
object Version extends Item[Int]("version")
val db: Database = ???
val version: Int = db.get(Version)
trait EnumLike {
type Value
def value: Value
}
trait StringEnumLike extends EnumLike {
type Value = String
}
trait EnumCompanion[A <: EnumLike] {
def values: Seq[A]
def valueOf(value: A#Value): Option[A] = values.find(_.value == value)
implicit val companion: EnumCompanion[A] = this
implicit def optionalTypeBinder(implicit binder: TypeBinder[Option[A#Value]]): TypeBinder[Option[A]] = binder.map(_.flatMap(valueOf))
implicit def typeBinder(implicit binder: TypeBinder[Option[A#Value]]): TypeBinder[A] = optionalTypeBinder.map(_.get)
}
trait HasDefault[A <: EnumLike] {
def default: A
}
object HasDefault {
def apply[A <: EnumLike](value: => A): HasDefault[A] = new HasDefault[A] { val default = value }
def valueOf[A <: EnumLike: EnumCompanion: HasDefault](value: A#Value): A = {
implicitly[EnumCompanion[A]].valueOf(value) getOrElse implicitly[HasDefault[A]].default
}
}
abstract sealed class UserType(val value: String) extends StringEnumLike
object UserType extends EnumCompanion[UserType] {
case object Admin extends UserType("admin")
case object Regular extends UserType("regular")
case object Guest extends UserType("guest")
lazy val values = Seq(Admin, Regular, Guest)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment