|
|
|
package green.thisfieldwas.embracingnondeterminism.data
|
|
|
|
|
|
|
|
import green.thisfieldwas.embracingnondeterminism.util._
|
|
|
|
import org.scalacheck.Arbitrary
|
|
|
|
import org.scalacheck.Arbitrary.arbitrary
|
|
|
|
|
|
|
|
import scala.reflect.runtime.universe.TypeTag
|
|
|
|
|
|
|
|
/** Include this trait to check that your context `F[_]` conforms to the
|
|
|
|
* Semigroup laws. Call the `checkSemigroupLaws()` function within your laws
|
|
|
|
* spec to register the associated properties.
|
|
|
|
*/
|
|
|
|
trait SemigroupLaws { this: Laws =>
|
|
|
|
|
|
|
|
import green.thisfieldwas.embracingnondeterminism.syntax.semigroup._
|
|
|
|
|
|
|
|
/** Defined per Semigroup laws taken from the Haskell wiki:
|
|
|
|
* [[https://wiki.haskell.org/Data.Semigroup#Semigroup_Laws]]
|
|
|
|
*
|
|
|
|
* @tparam S
|
|
|
|
* The Semigroup type being tested.
|
|
|
|
*/
|
|
|
|
def checkSemigroupLaws[S: Semigroup: Arbitrary]()(implicit TT: TypeTag[S]): Unit = {
|
|
|
|
// Combining three values can be performed in any order and produce the
|
|
|
|
// same result.
|
|
|
|
property(s"${TT.name} Semigroup is associative") {
|
|
|
|
forAll(for {
|
|
|
|
a <- arbitrary[S]
|
|
|
|
b <- arbitrary[S]
|
|
|
|
c <- arbitrary[S]
|
|
|
|
} yield (a, b, c)) { case (a, b, c) =>
|
|
|
|
a |+| (b |+| c) mustBe (a |+| b) |+| c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|