Skip to content

Instantly share code, notes, and snippets.

@bishabosha
Created May 9, 2022 20:41
Show Gist options
  • Save bishabosha/45cf41dcf843bad145b0884eb5fb52cc to your computer and use it in GitHub Desktop.
Save bishabosha/45cf41dcf843bad145b0884eb5fb52cc to your computer and use it in GitHub Desktop.
Showing how the type class derivation mechanism can be used to add methods to the companion object with low boilerplate from the client side
trait Plugin:
type Companion
val exports: Companion
object Plugin:
transparent inline def exports[P <: Plugin](using plugin: P): plugin.exports.type = plugin.exports
trait Hashable[-T] extends Plugin:
extension (t: T) protected def computeHash: Long
trait Companion:
def hash(t: T): Long = t.computeHash
object exports extends Companion
object Hashable:
def derived[T]: Hashable[T] = new Hashable[T]:
extension (t: T) protected def computeHash: Long = System.identityHashCode(t).toLong
trait Flags[T <: reflect.Enum] extends Plugin:
outer =>
opaque type FlagSet = Long
trait Companion:
type FlagSet = outer.FlagSet
def EmptyFlagSet: outer.FlagSet = 0L
object exports extends Companion
object FlagSet:
extension (flags: FlagSet)
def isEmpty = flags == 0L
def | (flag: T): FlagSet = flags | flag.asFlags
extension (flag: T)
def asFlags: FlagSet = 1L << flag.ordinal
object Flags:
def derived[T <: reflect.Enum]: Flags[T] = new Flags[T] {}
enum Foo derives Hashable, Flags:
case A, B, C
object Foo:
private transparent inline def hash = Plugin.exports[Hashable[Foo]]
private transparent inline def flags = Plugin.exports[Flags[Foo]]
export hash.*, flags.*
@main def Test =
println(Foo.hash(Foo.A))
println(Foo.A.asFlags)
println(Foo.B.asFlags)
println(Foo.C.asFlags)
println(Foo.EmptyFlagSet)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment