diff --git a/src/main/scala/fpspeedrun/Eq.scala b/src/main/scala/fpspeedrun/Eq.scala index 1f0649b..db05f0d 100644 --- a/src/main/scala/fpspeedrun/Eq.scala +++ b/src/main/scala/fpspeedrun/Eq.scala @@ -37,5 +37,13 @@ object Eq extends StdEqInstances { } trait StdEqInstances extends StdOrdInstances[Eq]{ - implicit def eitherEq[A: Eq, B: Eq]: Eq[Either[A, B]] = ??? + 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)) => 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 bde003a..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]{ @@ -21,19 +22,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(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(x.value * y.value) + } } @@ -48,5 +63,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..b4d1aef 100644 --- a/src/main/scala/fpspeedrun/Ord.scala +++ b/src/main/scala/fpspeedrun/Ord.scala @@ -70,6 +70,17 @@ 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]] = ??? -} \ 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 = { + (x, y) match { + 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 607767d..406f86b 100644 --- a/src/main/scala/fpspeedrun/ZipList.scala +++ b/src/main/scala/fpspeedrun/ZipList.scala @@ -1,5 +1,12 @@ 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]] @@ -25,17 +32,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)) => 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)(_ |+| _) + } + + 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)(_ |+| _) + } + } + + implicit def zipListEq[A: Eq]: Eq[ZipList[A]] = (x: ZipList[A], y: ZipList[A]) => { + 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)(_ + _) + } + + 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) + } + } + + 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)(_ / _) -> 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)(_ + _) - implicit def zipListMonoid[A: Monoid]: Monoid[ZipList[A]] = ??? + override def times(x: ZipList[A], y: ZipList[A]): ZipList[A] = x.zipWith(y)(_ * _) - 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)(_ / _) + } - 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)(_ + _) + } - implicit def zipListFrac[A: Frac]: Frac[ZipList[A]] = ??? + 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) + } + } } diff --git a/src/main/scala/fpspeedrun/syntax/package.scala b/src/main/scala/fpspeedrun/syntax/package.scala index 4682d78..5118cd1 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))) } + } } }