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
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]]()
|
|
}
|
|
|