Skip to content

Instantly share code, notes, and snippets.

@zainab-ali
Created March 20, 2017 22:54
Show Gist options
  • Save zainab-ali/bb21f798b87340692760277484158be1 to your computer and use it in GitHub Desktop.
Save zainab-ali/bb21f798b87340692760277484158be1 to your computer and use it in GitHub Desktop.
object gist {
import shapeless._
trait Semigroup[A] {
def combine(a0: A, a1: A): A
}
implicit final class SemigroupCombineOps[A](a0: A)(implicit S: Semigroup[A]) {
def combine(a1: A): A = S.combine(a0, a1)
}
//The HList here is a meta tag - we never instantiate it. The order of elements in the hlist isn't important.
case class Quantity[H <: HList](value: Double)
object Quantity {
implicit def quantitySemigroup[H <: HList]: Semigroup[Quantity[H]] = new Semigroup[Quantity[H]] {
def combine(q0: Quantity[H], q1: Quantity[H]): Quantity[H] = Quantity[H](q0.value + q1.value)
}
}
object ThisCantWork {
type Foo
type Bar
//for all intents and purposes, these represent the same thing. Physically, we should be able to combine them.
val q0: Quantity[Foo :: Bar :: HNil] = Quantity(1.0)
val q1: Quantity[Bar :: Foo :: HNil] = Quantity(2.0)
//of course, we can't combine them - the types are different
//q0 combine q1
}
object WorkAround {
import shapeless.ops.hlist.Align
//we can safely cast, since both hlists have the same elements
implicit def realignQuantity[A <: HList, B <: HList](q: Quantity[A])(implicit ev: Align[A, B]): Quantity[B] = q.asInstanceOf[Quantity[B]]
type Foo
type Bar
val q0: Quantity[Foo :: Bar :: HNil] = Quantity(1.0)
val q1: Quantity[Bar :: Foo :: HNil] = Quantity(2.0)
q0 combine q1
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment