Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close #82 - Add OptionSemiGroup and OptionMonoid #85

Merged
merged 1 commit into from
Sep 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/main/scala/just/fp/Monoid.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ trait Monoid[A] extends SemiGroup[A] {
def monoidLaw: MonoidLaw = new MonoidLaw {}
}

object Monoid {
object Monoid extends OptionMonoidInstance {

implicit def listMonoid[A]: Monoid[List[A]] = new Monoid[List[A]] with ListSemiGroup[A] {
override def zero: List[A] = Nil
Expand Down Expand Up @@ -75,4 +75,14 @@ object Monoid {
override def zero: BigDecimal = BigDecimal(0)
}

}
}

private[fp] trait OptionMonoidInstance extends OptionSemiGroupInstance {
implicit def optionMonoid[A](implicit F0: SemiGroup[A]): Monoid[Option[A]] =
new Monoid[Option[A]] with OptionSemigroup[A] {

override implicit def F: SemiGroup[A] = F0

override def zero: Option[A] = None
}
}
26 changes: 25 additions & 1 deletion src/main/scala/just/fp/SemiGroup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ trait SemiGroup[A] {
def append(a1: A, a2: => A): A
}

object SemiGroup {
object SemiGroup extends OptionSemiGroupInstance {

trait ListSemiGroup[A] extends SemiGroup[List[A]] {
override def append(a1: List[A], a2: => List[A]): List[A] = a1 ++ a2
Expand Down Expand Up @@ -60,3 +60,27 @@ object SemiGroup {
}
implicit val bigDecimalSemiGroup: SemiGroup[BigDecimal] = new BigDecimalSemiGroup {}
}

private[fp] trait OptionSemigroup[A] extends SemiGroup[Option[A]] {

implicit def F: SemiGroup[A]

override def append(a1: Option[A], a2: => Option[A]): Option[A] = (a1, a2) match {
case (Some(x), Some(y)) =>
Some(implicitly[SemiGroup[A]].append(x, y))
case (Some(x), None) =>
Some(x)
case (None, Some(y)) =>
Some(y)
case (None, None) =>
None
}
}

private[fp] trait OptionSemiGroupInstance {

implicit def optionSemigroup[A](implicit F0: SemiGroup[A]): SemiGroup[Option[A]] =
new OptionSemigroup[A] {
override implicit def F: SemiGroup[A] = F0
}
}
12 changes: 11 additions & 1 deletion src/test/scala/just/fp/MonoidSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import hedgehog.runner._
object MonoidSpec extends Properties {

override def tests: List[Test] = List(
property("testListMonoidLaw", ListMonoidLaws.laws)
property("testOptionMonoidLaw", OptionMonoidLaws.laws)
, property("testListMonoidLaw", ListMonoidLaws.laws)
, property("testVectorMonoidLaw", VectorMonoidLaws.laws)
, property("testStringMonoidLaw", StringMonoidLaws.laws)
, property("testByteMonoidLaw", ByteMonoidLaws.laws)
Expand Down Expand Up @@ -40,6 +41,15 @@ object MonoidSpec extends Properties {
)
}

object OptionMonoidLaws {
def genOption: Gen[Option[Int]] = Gens.genOption(Gens.genIntFromMinToMax)

def laws: Property =
Specs.monoidLaws.laws[Option[Int]](
genOption
)
}

object StringMonoidLaws {
def genString: Gen[String] = Gens.genUnicodeString

Expand Down
4 changes: 3 additions & 1 deletion src/test/scala/just/fp/syntax/SemiGroupSyntaxSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ object SemiGroupSyntaxSpec extends Properties {
import just.fp._

override def tests: List[Test] = List(
property("test List |+| List", testPlus(Gens.genList(Gens.genIntFromMinToMax, 10)))
property("test Option |+| Option", testPlus(Gens.genOption(Gens.genIntFromMinToMax)))
, property("test List |+| List", testPlus(Gens.genList(Gens.genIntFromMinToMax, 10)))
, property("test Vector |+| Vector", testPlus(Gens.genVector(Gens.genIntFromMinToMax, 10)))
, property("test String |+| String", testPlus(Gens.genUnicodeString))
, property("test Byte |+| Byte", testPlus(Gens.genByteFromMinToMax))
Expand All @@ -22,6 +23,7 @@ object SemiGroupSyntaxSpec extends Properties {
, property("test Long |+| Long", testPlus(Gens.genLongFromMinToMax))
, property("test BigInt |+| BigInt", testPlus(Gens.genBigInt))
, property("test BigDecimal |+| BigDecimal", testPlus(Gens.genBigDecimal))
, property("test Option.mappend(Option)", testMappend(Gens.genOption(Gens.genIntFromMinToMax)))
, property("test List.mappend(List)", testMappend(Gens.genList(Gens.genIntFromMinToMax, 10)))
, property("test Vector.mappend(Vector)", testMappend(Gens.genVector(Gens.genIntFromMinToMax, 10)))
, property("test String.mappend(String)", testMappend(Gens.genUnicodeString))
Expand Down