You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

54 lines
1.5 KiB

package green.thisfieldwas.embracingnondeterminism.stdlib
import green.thisfieldwas.embracingnondeterminism.data.{Semigroup, SemigroupLaws}
import green.thisfieldwas.embracingnondeterminism.util.Laws
import org.scalacheck.Arbitrary.arbitrary
import org.scalacheck.{Arbitrary, Gen}
/** Proves that Scala's List conforms to the following typeclasses:
* - Functor
* - Semigroup
*/
class ListSpec extends Laws with SemigroupLaws {
property("List.map() preserves identity functions") {
forAll(arbitrary[List[Int]]) { fa =>
fa.map(identity) mustBe identity(fa)
}
}
property("List.map() preserves function composition") {
forAll(for {
fa <- arbitrary[List[Double]]
f <- arbitrary[Double => String]
g <- arbitrary[String => Int]
} yield (fa, f, g)) { case (fa, f, g) =>
fa.map(g compose f) mustBe fa.map(f).map(g)
}
}
/** Non-empty Lists specifically form a Semigroup.
*
* @tparam A
* Any type held by a List.
* @return
* The Arbitrary generator for a non-empty List.
*/
implicit def arbitraryNonEmptySet[A: Arbitrary]: Arbitrary[List[A]] = Arbitrary {
for {
length <- Gen.sized(n => Gen.choose(1, n.max(1)))
list <- Gen.listOfN(length, arbitrary[A])
} yield list
}
/** List forms a Semigroup under concatenation.
*
* @tparam A
* Any type held by the List.
* @return
* The Semigroup instance for List.
*/
implicit def listSemigroup[A: Arbitrary]: Semigroup[List[A]] = _ ++ _
checkSemigroupLaws[List[Int]]()
}