Skip to content

Instantly share code, notes, and snippets.

@ahoy-jon
Forked from fsarradin/Point.scala
Last active December 19, 2015 04:49
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 ahoy-jon/5899968 to your computer and use it in GitHub Desktop.
Save ahoy-jon/5899968 to your computer and use it in GitHub Desktop.
object Point {
trait PointAdder[P1, P2] {
def add(p1: P1, p2: P2): Point3D
}
case class Point2D(x: Int, y: Int)
case class Point3D(x: Int, y: Int, z: Int)
implicit object Point2DAdder extends PointAdder[Point2D, Point2D] {
def add(p1: Point2D, p2: Point2D): Point3D = Point3D(p1.x + p2.x, p1.y + p2.y, 0)
}
implicit object Point3DAdder extends PointAdder[Point3D, Point3D] {
def add(p1: Point3D, p2: Point3D): Point3D = Point3D(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z)
}
implicit object Point2DPoint3DAdder extends PointAdder[Point2D, Point3D] {
def add(p1: Point2D, p2: Point3D): Point3D = Point3D(p1.x + p2.x, p1.y + p2.y, p2.z)
}
implicit object Point3DPoint2DAdder extends PointAdder[Point3D, Point2D] {
def add(p1: Point3D, p2: Point2D): Point3D = Point3D(p1.x + p2.x, p1.y + p2.y, p1.z)
}
def main(args: Array[String]) {
val point1 = Point2D(1, 2)
val point2 = Point3D(1, 2, 3)
println(implicitly[PointAdder[Point2D, Point3D]].add(point1, point2))
}
}
import shapeless._
object MonoidExamples extends App {
import MonoidSyntax._
case class Point2D(x: Int, y: Int, labels:Set[String])
case class Point3D(x: Int, y: Int, z: Int, labels:Set[String])
object Point2D {
implicit def toPoint3D(p:Point2D):Point3D = Point3D(p.x,p.y,0, p.labels)
}
val a = Point2D(1,2, Set("ahoy"))
val b = Point3D(1,2,3, Set("plouf"))
implicit val point2DMonoid = TypeClass[Monoid,Point2D]
implicit val point3DMonoid = TypeClass[Monoid,Point3D]
println(a |+| a)
println(b |+| b)
println(b |+| a)
}
/**
* Pedagogic subset of the Scalaz monoid
*/
trait Monoid[T] {
def zero : T
def append(a : T, b : T) : T
}
object Monoid extends TypeClassCompanion[Monoid] {
def mzero[T](implicit mt : Monoid[T]) = mt.zero
implicit def booleanMonoid : Monoid[Boolean] = new Monoid[Boolean] {
def zero = false
def append(a : Boolean, b : Boolean) = a || b
}
implicit def intMonoid : Monoid[Int] = new Monoid[Int] {
def zero = 0
def append(a : Int, b : Int) = a+b
}
implicit def doubleMonoid : Monoid[Double] = new Monoid[Double] {
def zero = 0.0
def append(a : Double, b : Double) = a+b
}
implicit def setMonoid[T]: Monoid[Set[T]] = new Monoid[Set[T]] {
def append(a: Set[T], b: Set[T]): Set[T] = a.++(b)
def zero: Set[T] = Set.empty
}
implicit def stringMonoid : Monoid[String] = new Monoid[String] {
def zero = ""
def append(a : String, b : String) = a+b
}
implicit val monoidInstance: ProductTypeClass[Monoid] = new ProductTypeClass[Monoid] {
def emptyProduct = new Monoid[HNil] {
def zero = HNil
def append(a : HNil, b : HNil) = HNil
}
def product[F, T <: HList](FHead : Monoid[F], FTail : Monoid[T]) = new Monoid[F :: T] {
def zero = FHead.zero :: FTail.zero
def append(a : F :: T, b : F :: T) = FHead.append(a.head, b.head) :: FTail.append(a.tail, b.tail)
}
def project[F, G](instance : => Monoid[G], to : F => G, from : G => F) = new Monoid[F] {
def zero = from(instance.zero)
def append(a : F, b : F) = from(instance.append(to(a), to(b)))
}
}
}
trait MonoidSyntax[T] {
def |+|(b : T) : T
}
object MonoidSyntax {
implicit def monoidSyntax[T](a : T)(implicit mt : Monoid[T]) : MonoidSyntax[T] = new MonoidSyntax[T] {
def |+|(b : T) = mt.append(a, b)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment