Skip to content

Instantly share code, notes, and snippets.

@mandubian
Created January 19, 2017 20:50
Show Gist options
  • Save mandubian/083abf83798f35ed42a140755bd90a7f to your computer and use it in GitHub Desktop.
Save mandubian/083abf83798f35ed42a140755bd90a7f to your computer and use it in GitHub Desktop.
trait Monoid[M <: AnyKind] {
type ->[_<:AnyKind, _<:AnyKind]
type I <: AnyKind
def unit: ->[I, M]
def mult(a: I -> M, b: I -> M): I -> M
}
object Monoid {
type Aux[M <: AnyKind, M0[_<:AnyKind, _<:AnyKind], I0 <: AnyKind] = Monoid[M] { type ->[a <: AnyKind, b <: AnyKind] = M0[a, b]; type I = I0 }
def apply[M <: AnyKind](implicit monoid: Monoid[M]): monoid.type = monoid
}
/** Sample with Int & integer multiplication */
implicit val MonoidIntMul: Monoid.Aux[Int, Function1, Unit] = new Monoid[Int] {
type ->[a, b] = Function1[a, b]
type I = Unit
val unit: Unit => Int = _ => 1
def mult(a: Unit => Int, b: Unit => Int): Unit => Int = _ => a(()) * b(())
}
assert(Monoid[Int].unit(()) == 1)
assert(Monoid[Int].mult(_ => 5, _ => 10)(()) == 50)
type Id[A] = A
implicit val MonoidList: Monoid.Aux[List, ~>, Id] = new Monoid[List] {
type ->[a[_], b[_]] = ~>[a, b]
type I[a] = Id[a]
val unit: Id ~> List = new (Id ~> List) {
def apply[A](id: Id[A]): List[A] = List()
}
def mult(a: Id ~> List, b: Id ~> List): Id ~> List = new (Id ~> List) {
def apply[A](id: Id[A]): List[A] = a(id) ++ b(id)
}
}
assert(Monoid[List].unit(0:Id[Int]) == List[Int]())
val l = new (Id ~> List) {
def apply[A](id: Id[A]): List[A] = List(id)
}
assert(Monoid[List].mult(l, l)(5: Id[Int]) == List(5, 5))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment