From ed966ca91f214c9fe025b6314201371766a6ecd1 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 24 Jun 2018 21:19:08 +0700 Subject: [PATCH 1/4] hw2 --- src/main/scala/fpspeedrun/Eq.scala | 8 +- src/main/scala/fpspeedrun/Monoid.scala | 25 +++++- src/main/scala/fpspeedrun/Ord.scala | 8 +- src/main/scala/fpspeedrun/ZipList.scala | 88 +++++++++++++++++-- .../scala/fpspeedrun/syntax/package.scala | 14 +-- 5 files changed, 124 insertions(+), 19 deletions(-) diff --git a/src/main/scala/fpspeedrun/Eq.scala b/src/main/scala/fpspeedrun/Eq.scala index 1f0649b..e04e280 100644 --- a/src/main/scala/fpspeedrun/Eq.scala +++ b/src/main/scala/fpspeedrun/Eq.scala @@ -37,5 +37,11 @@ object Eq extends StdEqInstances { } trait StdEqInstances extends StdOrdInstances[Eq]{ - implicit def eitherEq[A: Eq, B: Eq]: Eq[Either[A, B]] = ??? + implicit def eitherEq[A: Eq, B: Eq]: Eq[Either[A, B]] = (x: Either[A, B], y: Either[A, B]) => { + (x, y) match { + case (Left(a), Left(b)) => Eq[A].equal(a, b) + case (Right(a), Right(b)) => Eq[B].equal(a, b) + case _ => false + } + } } diff --git a/src/main/scala/fpspeedrun/Monoid.scala b/src/main/scala/fpspeedrun/Monoid.scala index bde003a..23b0e8f 100644 --- a/src/main/scala/fpspeedrun/Monoid.scala +++ b/src/main/scala/fpspeedrun/Monoid.scala @@ -21,19 +21,33 @@ object Monoid extends StdMonoidInstances[Monoid] { final case class Endo[A](run: A => A) extends AnyVal object Endo{ - implicit def endoMonoid[A]: Monoid[Endo[A]] = ??? + implicit def endoMonoid[A]: Monoid[Endo[A]] = new Monoid[Endo[A]] { + override def empty: Endo[A] = Endo(identity) + + override def combine(x: Endo[A], y: Endo[A]): Endo[A] = { + Endo(x.run andThen y.run) + } + } } final case class Sum[T](value: T) extends AnyVal with Wrapper[T] object Sum extends WrapperCompanion[Sum] { - implicit def sumMonoid[T: Num]: Monoid[Sum[T]] = ??? + implicit def sumMonoid[T: Num]: Monoid[Sum[T]] = new Monoid[Sum[T]] { + override def empty: Sum[T] = Sum(Num[T].zero) + + override def combine(x: Sum[T], y: Sum[T]): Sum[T] = Sum(Num[T].plus(x.value, y.value)) + } } final case class Prod[T](value: T) extends AnyVal with Wrapper[T] object Prod extends WrapperCompanion[Prod] { - implicit def prodMonoid[T: Num]: Monoid[Prod[T]] = ??? + implicit def prodMonoid[T: Num]: Monoid[Prod[T]] = new Monoid[Prod[T]] { + override def empty: Prod[T] = Prod(Num[T].one) + + override def combine(x: Prod[T], y: Prod[T]): Prod[T] = Prod(Num[T].times(x.value, y.value)) + } } @@ -48,5 +62,8 @@ trait StdMonoidInstances[TC[x] >: Monoid[x]] { override def combine(x: List[A], y: List[A]): List[A] = x ::: y } - final implicit def vectorMonoid[A]: TC[Vector[A]] = ??? + final implicit def vectorMonoid[A]: TC[Vector[A]] = new Monoid[Vector[A]] { + override def empty: Vector[A] = Vector.empty + override def combine(x: Vector[A], y: Vector[A]): Vector[A] = x ++ y + } } diff --git a/src/main/scala/fpspeedrun/Ord.scala b/src/main/scala/fpspeedrun/Ord.scala index f00201e..9978832 100644 --- a/src/main/scala/fpspeedrun/Ord.scala +++ b/src/main/scala/fpspeedrun/Ord.scala @@ -71,5 +71,9 @@ object Ord extends StdOrdInstances[Ord] { trait StdOrdInstances[TC[t] >: Ord[t]] extends StdNumInstances[TC]{ final implicit val stringOrd: TC[String] = byOrdering - final implicit def optionOrd[A: Ord]: TC[Option[A]] = ??? -} \ No newline at end of file + final implicit def optionOrd[A: Ord]: TC[Option[A]] = new Ord[Option[A]] { + override def compare(x: Option[A], y: Option[A]): Compare = { + Ord[Option[A]].compare(x, y) + } + } +} diff --git a/src/main/scala/fpspeedrun/ZipList.scala b/src/main/scala/fpspeedrun/ZipList.scala index 607767d..03bdadd 100644 --- a/src/main/scala/fpspeedrun/ZipList.scala +++ b/src/main/scala/fpspeedrun/ZipList.scala @@ -1,5 +1,6 @@ package fpspeedrun + trait ZipList[A] { def value: Either[A, List[A]] @@ -25,17 +26,90 @@ object ZipList { def apply[A](list: List[A]): ZipList[A] = Finite(list) def repeat[A](value: A): ZipList[A] = Repeat(value) - implicit def zipListSemigroup[A: Semigroup]: Semigroup[ZipList[A]] = ??? + private def ordZl[A: Ord](x: ZipList[A], y: ZipList[A]) = { + (x.value, y.value) match { + case (Left(a), Left(b)) => Ord[A].compare(a, b) + case (Left(a), Right(b)) => Ord.compareLists(List(a), b) + case (Right(a), Left(b)) => Ord.compareLists(List(b), a) + case (Right(a), Right(b)) => Ord.compareLists(a, b) + } + } + + implicit def zipListSemigroup[A: Semigroup]: Semigroup[ZipList[A]] = (x: ZipList[A], y: ZipList[A]) => { + x.zipWith(y)(Semigroup[A].combine) + } + + implicit def zipListMonoid[A: Monoid]: Monoid[ZipList[A]] = new Monoid[ZipList[A]] { + override def empty: ZipList[A] = Repeat(Monoid[A].empty) + + override def combine(x: ZipList[A], y: ZipList[A]): ZipList[A] = { + x.zipWith(y)(Monoid[A].combine) + } + } + + implicit def zipListEq[A: Eq]: Eq[ZipList[A]] = (x: ZipList[A], y: ZipList[A]) => { + Eq[Either[A, List[A]]].equal(x.value, y.value) + } + + implicit def zipListOrd[A: Ord]: Ord[ZipList[A]] = (x: ZipList[A], y: ZipList[A]) => { + ordZl(x, y) + } + + implicit def zipListNum[A: Num]: Num[ZipList[A]] = new Num[ZipList[A]] { + override def fromInt(x: Int): ZipList[A] = { + Repeat(Num[A].fromInt(x)) + } + + override def plus(x: ZipList[A], y: ZipList[A]): ZipList[A] = { + x.zipWith(y)(Num[A].plus) + } + + override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = { + x.zipWith(y)(Num[A].times) + } + + override def compare(x: ZipList[A], y: ZipList[A]): Ord.Compare = { + ordZl(x, y) + } + } + + implicit def zipListInteg[A: Integ]: Integ[ZipList[A]] = new Integ[ZipList[A]] { + override def quotRem(x: ZipList[A], y: ZipList[A]): (ZipList[A], ZipList[A]) = { + x.zipWith(y)(Integ[A].quot) -> x.zipWith(y)(Integ[A].rem) + } + + override def fromInt(x: Int): ZipList[A] = { + Repeat(Integ[A].fromInt(x)) + } + + override def plus(x: ZipList[A], y: ZipList[A]): ZipList[A] = x.zipWith(y)(Integ[A].plus) - implicit def zipListMonoid[A: Monoid]: Monoid[ZipList[A]] = ??? + override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = x.zipWith(y)(Integ[A].times) - implicit def zipListEq[A: Eq]: Eq[ZipList[A]] = ??? + override def compare(x: ZipList[A], y: ZipList[A]): Ord.Compare = { + ordZl(x, y) + } + } - implicit def zipListOrd[A: Ord]: Ord[ZipList[A]] = ??? + implicit def zipListFrac[A: Frac]: Frac[ZipList[A]] = new Frac[ZipList[A]] { + override def div(x: ZipList[A], y: ZipList[A]): ZipList[A] = { + x.zipWith(y)(Frac[A].div) + } - implicit def zipListNum[A: Num]: Num[ZipList[A]] = ??? + override def fromInt(x: Int): ZipList[A] = { + Repeat(Frac[A].fromInt(x)) + } - implicit def zipListInteg[A: Integ]: Integ[ZipList[A]] = ??? + override def plus(x: ZipList[A], y: ZipList[A]): ZipList[A] = { + x.zipWith(y)(Frac[A].plus) + } - implicit def zipListFrac[A: Frac]: Frac[ZipList[A]] = ??? + override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = { + x.zipWith(y)(Frac[A].times) + } + + override def compare(x: ZipList[A], y: ZipList[A]): Ord.Compare = { + ordZl(x, y) + } + } } diff --git a/src/main/scala/fpspeedrun/syntax/package.scala b/src/main/scala/fpspeedrun/syntax/package.scala index 4682d78..e33d5f6 100644 --- a/src/main/scala/fpspeedrun/syntax/package.scala +++ b/src/main/scala/fpspeedrun/syntax/package.scala @@ -47,14 +47,18 @@ object semigroup extends Semigroup.ToSemigroupOps { } } -object monoid extends Monoid.ToMonoidOps{ - def empty[T: Monoid]: T = ??? +object monoid extends Monoid.ToMonoidOps { + def empty[T: Monoid]: T = Monoid[T].empty implicit class ListOps[A](val xs: List[A]) extends AnyVal{ - def foldAll(implicit mon: Monoid[A]): A = ??? + def foldAll(implicit mon: Monoid[A]): A = xs.foldLeft(mon.empty) { case (a, b) => + mon.combine(a, b) + } - def foldMap[B: Monoid](f: A => B): B = ??? + def foldMap[B: Monoid](f: A => B): B = xs.map(f).foldAll - def foldVia[F[_]](implicit iso: Iso[A, F[A]], mon: Monoid[F[A]]): A = ??? + def foldVia[F[_]](implicit iso: Iso[A, F[A]], mon: Monoid[F[A]]): A = { + xs.foldLeft(iso.unwrap(mon.empty)) { case (a, b) => iso.unwrap(mon.combine(iso.wrap(a), iso.wrap(b))) } + } } } From 03d1ba7e965c5d390ea9959e96ccf9e4681e8b5a Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 24 Jun 2018 21:33:05 +0700 Subject: [PATCH 2/4] fix ident --- src/main/scala/fpspeedrun/syntax/package.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/fpspeedrun/syntax/package.scala b/src/main/scala/fpspeedrun/syntax/package.scala index e33d5f6..5118cd1 100644 --- a/src/main/scala/fpspeedrun/syntax/package.scala +++ b/src/main/scala/fpspeedrun/syntax/package.scala @@ -52,7 +52,7 @@ object monoid extends Monoid.ToMonoidOps { implicit class ListOps[A](val xs: List[A]) extends AnyVal{ def foldAll(implicit mon: Monoid[A]): A = xs.foldLeft(mon.empty) { case (a, b) => - mon.combine(a, b) + mon.combine(a, b) } def foldMap[B: Monoid](f: A => B): B = xs.map(f).foldAll From b922d6f224a9dcfdd23daaf717a0cbc2bf6ee9fc Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 24 Jun 2018 21:44:13 +0700 Subject: [PATCH 3/4] fix --- src/main/scala/fpspeedrun/Ord.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/scala/fpspeedrun/Ord.scala b/src/main/scala/fpspeedrun/Ord.scala index 9978832..0472a0e 100644 --- a/src/main/scala/fpspeedrun/Ord.scala +++ b/src/main/scala/fpspeedrun/Ord.scala @@ -73,7 +73,12 @@ trait StdOrdInstances[TC[t] >: Ord[t]] extends StdNumInstances[TC]{ final implicit val stringOrd: TC[String] = byOrdering final implicit def optionOrd[A: Ord]: TC[Option[A]] = new Ord[Option[A]] { override def compare(x: Option[A], y: Option[A]): Compare = { - Ord[Option[A]].compare(x, y) + (x, y) match { + case (Some(a), Some(b)) => Ord[A].compare(a, b) + case (None, None) => Ord.Compare.EQ + case (Some(_), None) => Ord.Compare.GT + case (None, Some(_)) => Ord.Compare.LT + } } } } From f9760922bace4ce4078e7901b8ce8fda9433b478 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 24 Jun 2018 22:11:35 +0700 Subject: [PATCH 4/4] apply syntax --- src/main/scala/fpspeedrun/Eq.scala | 6 +++-- src/main/scala/fpspeedrun/Monoid.scala | 5 +++-- src/main/scala/fpspeedrun/Ord.scala | 4 +++- src/main/scala/fpspeedrun/ZipList.scala | 30 +++++++++++++++---------- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/main/scala/fpspeedrun/Eq.scala b/src/main/scala/fpspeedrun/Eq.scala index e04e280..db05f0d 100644 --- a/src/main/scala/fpspeedrun/Eq.scala +++ b/src/main/scala/fpspeedrun/Eq.scala @@ -37,10 +37,12 @@ object Eq extends StdEqInstances { } trait StdEqInstances extends StdOrdInstances[Eq]{ + import fpspeedrun.syntax.eq._ + implicit def eitherEq[A: Eq, B: Eq]: Eq[Either[A, B]] = (x: Either[A, B], y: Either[A, B]) => { (x, y) match { - case (Left(a), Left(b)) => Eq[A].equal(a, b) - case (Right(a), Right(b)) => Eq[B].equal(a, b) + case (Left(a), Left(b)) => a === b + case (Right(a), Right(b)) => a === b case _ => false } } diff --git a/src/main/scala/fpspeedrun/Monoid.scala b/src/main/scala/fpspeedrun/Monoid.scala index 23b0e8f..b77f29d 100644 --- a/src/main/scala/fpspeedrun/Monoid.scala +++ b/src/main/scala/fpspeedrun/Monoid.scala @@ -2,6 +2,7 @@ package fpspeedrun import fpspeedrun.Iso.{Wrapper, WrapperCompanion} import simulacrum.typeclass import syntax.semigroup._ +import syntax.num._ @typeclass trait Monoid[A] extends Semigroup[A] with Default[A]{ @@ -36,7 +37,7 @@ object Sum extends WrapperCompanion[Sum] { implicit def sumMonoid[T: Num]: Monoid[Sum[T]] = new Monoid[Sum[T]] { override def empty: Sum[T] = Sum(Num[T].zero) - override def combine(x: Sum[T], y: Sum[T]): Sum[T] = Sum(Num[T].plus(x.value, y.value)) + override def combine(x: Sum[T], y: Sum[T]): Sum[T] = Sum(x.value + y.value) } } @@ -46,7 +47,7 @@ object Prod extends WrapperCompanion[Prod] { implicit def prodMonoid[T: Num]: Monoid[Prod[T]] = new Monoid[Prod[T]] { override def empty: Prod[T] = Prod(Num[T].one) - override def combine(x: Prod[T], y: Prod[T]): Prod[T] = Prod(Num[T].times(x.value, y.value)) + override def combine(x: Prod[T], y: Prod[T]): Prod[T] = Prod(x.value * y.value) } } diff --git a/src/main/scala/fpspeedrun/Ord.scala b/src/main/scala/fpspeedrun/Ord.scala index 0472a0e..b4d1aef 100644 --- a/src/main/scala/fpspeedrun/Ord.scala +++ b/src/main/scala/fpspeedrun/Ord.scala @@ -70,11 +70,13 @@ object Ord extends StdOrdInstances[Ord] { } trait StdOrdInstances[TC[t] >: Ord[t]] extends StdNumInstances[TC]{ + import syntax.ord._ + final implicit val stringOrd: TC[String] = byOrdering final implicit def optionOrd[A: Ord]: TC[Option[A]] = new Ord[Option[A]] { override def compare(x: Option[A], y: Option[A]): Compare = { (x, y) match { - case (Some(a), Some(b)) => Ord[A].compare(a, b) + case (Some(a), Some(b)) => a <=> b case (None, None) => Ord.Compare.EQ case (Some(_), None) => Ord.Compare.GT case (None, Some(_)) => Ord.Compare.LT diff --git a/src/main/scala/fpspeedrun/ZipList.scala b/src/main/scala/fpspeedrun/ZipList.scala index 03bdadd..406f86b 100644 --- a/src/main/scala/fpspeedrun/ZipList.scala +++ b/src/main/scala/fpspeedrun/ZipList.scala @@ -1,5 +1,11 @@ package fpspeedrun +import syntax.ord._ +import syntax.num._ +import syntax.semigroup._ +import syntax.integ._ +import syntax.frac._ +import syntax.eq._ trait ZipList[A] { def value: Either[A, List[A]] @@ -28,7 +34,7 @@ object ZipList { private def ordZl[A: Ord](x: ZipList[A], y: ZipList[A]) = { (x.value, y.value) match { - case (Left(a), Left(b)) => Ord[A].compare(a, b) + case (Left(a), Left(b)) => a <=> b case (Left(a), Right(b)) => Ord.compareLists(List(a), b) case (Right(a), Left(b)) => Ord.compareLists(List(b), a) case (Right(a), Right(b)) => Ord.compareLists(a, b) @@ -36,19 +42,19 @@ object ZipList { } implicit def zipListSemigroup[A: Semigroup]: Semigroup[ZipList[A]] = (x: ZipList[A], y: ZipList[A]) => { - x.zipWith(y)(Semigroup[A].combine) + x.zipWith(y)(_ |+| _) } implicit def zipListMonoid[A: Monoid]: Monoid[ZipList[A]] = new Monoid[ZipList[A]] { override def empty: ZipList[A] = Repeat(Monoid[A].empty) override def combine(x: ZipList[A], y: ZipList[A]): ZipList[A] = { - x.zipWith(y)(Monoid[A].combine) + x.zipWith(y)(_ |+| _) } } implicit def zipListEq[A: Eq]: Eq[ZipList[A]] = (x: ZipList[A], y: ZipList[A]) => { - Eq[Either[A, List[A]]].equal(x.value, y.value) + x.value === y.value } implicit def zipListOrd[A: Ord]: Ord[ZipList[A]] = (x: ZipList[A], y: ZipList[A]) => { @@ -61,11 +67,11 @@ object ZipList { } override def plus(x: ZipList[A], y: ZipList[A]): ZipList[A] = { - x.zipWith(y)(Num[A].plus) + x.zipWith(y)(_ + _) } override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = { - x.zipWith(y)(Num[A].times) + x.zipWith(y)(_ * _) } override def compare(x: ZipList[A], y: ZipList[A]): Ord.Compare = { @@ -75,16 +81,16 @@ object ZipList { implicit def zipListInteg[A: Integ]: Integ[ZipList[A]] = new Integ[ZipList[A]] { override def quotRem(x: ZipList[A], y: ZipList[A]): (ZipList[A], ZipList[A]) = { - x.zipWith(y)(Integ[A].quot) -> x.zipWith(y)(Integ[A].rem) + x.zipWith(y)(_ / _) -> x.zipWith(y)(_ % _) } override def fromInt(x: Int): ZipList[A] = { Repeat(Integ[A].fromInt(x)) } - override def plus(x: ZipList[A], y: ZipList[A]): ZipList[A] = x.zipWith(y)(Integ[A].plus) + override def plus(x: ZipList[A], y: ZipList[A]): ZipList[A] = x.zipWith(y)(_ + _) - override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = x.zipWith(y)(Integ[A].times) + override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = x.zipWith(y)(_ * _) override def compare(x: ZipList[A], y: ZipList[A]): Ord.Compare = { ordZl(x, y) @@ -93,7 +99,7 @@ object ZipList { implicit def zipListFrac[A: Frac]: Frac[ZipList[A]] = new Frac[ZipList[A]] { override def div(x: ZipList[A], y: ZipList[A]): ZipList[A] = { - x.zipWith(y)(Frac[A].div) + x.zipWith(y)(_ / _) } override def fromInt(x: Int): ZipList[A] = { @@ -101,11 +107,11 @@ object ZipList { } override def plus(x: ZipList[A], y: ZipList[A]): ZipList[A] = { - x.zipWith(y)(Frac[A].plus) + x.zipWith(y)(_ + _) } override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = { - x.zipWith(y)(Frac[A].times) + x.zipWith(y)(_ * _) } override def compare(x: ZipList[A], y: ZipList[A]): Ord.Compare = {