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

Swap type parameter order in OneAnd #598

Merged
merged 1 commit into from
Nov 4, 2015
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
64 changes: 32 additions & 32 deletions core/src/main/scala/cats/data/OneAnd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import scala.collection.mutable.ListBuffer
* used to represent a List which is guaranteed to not be empty:
*
* {{{
* type NonEmptyList[A] = OneAnd[A, List]
* type NonEmptyList[A] = OneAnd[List, A]
* }}}
*/
final case class OneAnd[A, F[_]](head: A, tail: F[A]) {
final case class OneAnd[F[_], A](head: A, tail: F[A]) {

/**
* Combine the head and tail into a single `F[A]` value.
Expand All @@ -32,7 +32,7 @@ final case class OneAnd[A, F[_]](head: A, tail: F[A]) {
/**
* Append another OneAnd to this
*/
def combine(other: OneAnd[A, F])(implicit F: MonadCombine[F]): OneAnd[A, F] =
def combine(other: OneAnd[F, A])(implicit F: MonadCombine[F]): OneAnd[F, A] =
OneAnd(head, F.combine(tail, F.combine(F.pure(other.head), other.tail)))

/**
Expand Down Expand Up @@ -69,11 +69,11 @@ final case class OneAnd[A, F[_]](head: A, tail: F[A]) {
* Typesafe equality operator.
*
* This method is similar to == except that it only allows two
* OneAnd[A, F] values to be compared to each other, and uses
* OneAnd[F, A] values to be compared to each other, and uses
* equality provided by Eq[_] instances, rather than using the
* universal equality provided by .equals.
*/
def ===(that: OneAnd[A, F])(implicit A: Eq[A], FA: Eq[F[A]]): Boolean =
def ===(that: OneAnd[F, A])(implicit A: Eq[A], FA: Eq[F[A]]): Boolean =
A.eqv(head, that.head) && FA.eqv(tail, that.tail)

/**
Expand All @@ -89,41 +89,41 @@ final case class OneAnd[A, F[_]](head: A, tail: F[A]) {

trait OneAndInstances extends OneAndLowPriority1 {

implicit def oneAndEq[A, F[_]](implicit A: Eq[A], FA: Eq[F[A]]): Eq[OneAnd[A, F]] =
new Eq[OneAnd[A, F]]{
def eqv(x: OneAnd[A, F], y: OneAnd[A, F]): Boolean = x === y
implicit def oneAndEq[A, F[_]](implicit A: Eq[A], FA: Eq[F[A]]): Eq[OneAnd[F, A]] =
new Eq[OneAnd[F, A]]{
def eqv(x: OneAnd[F, A], y: OneAnd[F, A]): Boolean = x === y
}

implicit def oneAndShow[A, F[_]](implicit A: Show[A], FA: Show[F[A]]): Show[OneAnd[A, F]] =
Show.show[OneAnd[A, F]](_.show)
implicit def oneAndShow[A, F[_]](implicit A: Show[A], FA: Show[F[A]]): Show[OneAnd[F, A]] =
Show.show[OneAnd[F, A]](_.show)

implicit def oneAndSemigroupK[F[_]: MonadCombine]: SemigroupK[OneAnd[?, F]] =
new SemigroupK[OneAnd[?, F]] {
def combine[A](a: OneAnd[A, F], b: OneAnd[A, F]): OneAnd[A, F] =
implicit def oneAndSemigroupK[F[_]: MonadCombine]: SemigroupK[OneAnd[F, ?]] =
new SemigroupK[OneAnd[F, ?]] {
def combine[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] =
a combine b
}

implicit def oneAndSemigroup[F[_]: MonadCombine, A]: Semigroup[OneAnd[A, F]] =
implicit def oneAndSemigroup[F[_]: MonadCombine, A]: Semigroup[OneAnd[F, A]] =
oneAndSemigroupK.algebra

implicit def oneAndFoldable[F[_]](implicit foldable: Foldable[F]): Foldable[OneAnd[?,F]] =
new Foldable[OneAnd[?,F]] {
override def foldLeft[A, B](fa: OneAnd[A, F], b: B)(f: (B, A) => B): B =
implicit def oneAndFoldable[F[_]](implicit foldable: Foldable[F]): Foldable[OneAnd[F, ?]] =
new Foldable[OneAnd[F, ?]] {
override def foldLeft[A, B](fa: OneAnd[F, A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)
override def foldRight[A, B](fa: OneAnd[A, F], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
override def foldRight[A, B](fa: OneAnd[F, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
fa.foldRight(lb)(f)
override def isEmpty[A](fa: OneAnd[A, F]): Boolean = false
override def isEmpty[A](fa: OneAnd[F, A]): Boolean = false
}

implicit def oneAndMonad[F[_]](implicit monad: MonadCombine[F]): Monad[OneAnd[?, F]] =
new Monad[OneAnd[?, F]] {
override def map[A, B](fa: OneAnd[A,F])(f: A => B): OneAnd[B, F] =
implicit def oneAndMonad[F[_]](implicit monad: MonadCombine[F]): Monad[OneAnd[F, ?]] =
new Monad[OneAnd[F, ?]] {
override def map[A, B](fa: OneAnd[F, A])(f: A => B): OneAnd[F, B] =
OneAnd(f(fa.head), monad.map(fa.tail)(f))

def pure[A](x: A): OneAnd[A, F] =
def pure[A](x: A): OneAnd[F, A] =
OneAnd(x, monad.empty)

def flatMap[A, B](fa: OneAnd[A, F])(f: A => OneAnd[B, F]): OneAnd[B, F] = {
def flatMap[A, B](fa: OneAnd[F, A])(f: A => OneAnd[F, B]): OneAnd[F, B] = {
val end = monad.flatMap(fa.tail) { a =>
val fa = f(a)
monad.combine(monad.pure(fa.head), fa.tail)
Expand All @@ -135,10 +135,10 @@ trait OneAndInstances extends OneAndLowPriority1 {
}

trait OneAndLowPriority0 {
implicit val nelComonad: Comonad[OneAnd[?, List]] =
new Comonad[OneAnd[?, List]] {
implicit val nelComonad: Comonad[OneAnd[List, ?]] =
new Comonad[OneAnd[List, ?]] {

def coflatMap[A, B](fa: OneAnd[A, List])(f: OneAnd[A, List] => B): OneAnd[B, List] = {
def coflatMap[A, B](fa: OneAnd[List, A])(f: OneAnd[List, A] => B): OneAnd[List, B] = {
@tailrec def consume(as: List[A], buf: ListBuffer[B]): List[B] =
as match {
case Nil => buf.toList
Expand All @@ -147,18 +147,18 @@ trait OneAndLowPriority0 {
OneAnd(f(fa), consume(fa.tail, ListBuffer.empty))
}

def extract[A](fa: OneAnd[A, List]): A =
def extract[A](fa: OneAnd[List, A]): A =
fa.head

def map[A, B](fa: OneAnd[A, List])(f: A => B): OneAnd[B, List] =
def map[A, B](fa: OneAnd[List, A])(f: A => B): OneAnd[List, B] =
OneAnd(f(fa.head), fa.tail.map(f))
}
}

trait OneAndLowPriority1 extends OneAndLowPriority0 {
implicit def oneAndFunctor[F[_]](implicit F: Functor[F]): Functor[OneAnd[?, F]] =
new Functor[OneAnd[?, F]] {
def map[A, B](fa: OneAnd[A, F])(f: A => B): OneAnd[B, F] =
implicit def oneAndFunctor[F[_]](implicit F: Functor[F]): Functor[OneAnd[F, ?]] =
new Functor[OneAnd[F, ?]] {
def map[A, B](fa: OneAnd[F, A])(f: A => B): OneAnd[F, B] =
OneAnd(f(fa.head), F.map(fa.tail)(f))
}
}
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/scala/cats/data/package.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package cats

package object data {
type NonEmptyList[A] = OneAnd[A, List]
type NonEmptyVector[A] = OneAnd[A, Vector]
type NonEmptyStream[A] = OneAnd[A, Stream]
type NonEmptyList[A] = OneAnd[List, A]
type NonEmptyVector[A] = OneAnd[Vector, A]
type NonEmptyStream[A] = OneAnd[Stream, A]
type ValidatedNel[E, A] = Validated[NonEmptyList[E], A]

def NonEmptyList[A](head: A, tail: List[A] = Nil): NonEmptyList[A] =
OneAnd(head, tail)
def NonEmptyList[A](head: A, tail: A*): NonEmptyList[A] =
OneAnd[A, List](head, tail.toList)
OneAnd[List, A](head, tail.toList)

def NonEmptyVector[A](head: A, tail: Vector[A] = Vector.empty): NonEmptyVector[A] =
OneAnd(head, tail)
Expand Down
2 changes: 1 addition & 1 deletion laws/src/main/scala/cats/laws/discipline/Arbitrary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object arbitrary {
implicit def constArbitrary[A, B](implicit A: Arbitrary[A]): Arbitrary[Const[A, B]] =
Arbitrary(A.arbitrary.map(Const[A, B]))

implicit def oneAndArbitrary[F[_], A](implicit A: Arbitrary[A], F: Arbitrary[F[A]]): Arbitrary[OneAnd[A, F]] =
implicit def oneAndArbitrary[F[_], A](implicit A: Arbitrary[A], F: Arbitrary[F[A]]): Arbitrary[OneAnd[F, A]] =
Arbitrary(F.arbitrary.flatMap(fa => A.arbitrary.map(a => OneAnd(a, fa))))

implicit def xorArbitrary[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[A Xor B] =
Expand Down
6 changes: 3 additions & 3 deletions tests/src/test/scala/cats/tests/ListWrapper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ object ListWrapper {
def synthesize[A: Arbitrary]: Arbitrary[ListWrapper[A]] = implicitly
}

implicit val listWrapperOneAndArbitraryK: ArbitraryK[OneAnd[?, ListWrapper]] =
new ArbitraryK[OneAnd[?, ListWrapper]] {
def synthesize[A: Arbitrary]: Arbitrary[OneAnd[A, ListWrapper]] = implicitly
implicit val listWrapperOneAndArbitraryK: ArbitraryK[OneAnd[ListWrapper, ?]] =
new ArbitraryK[OneAnd[ListWrapper, ?]] {
def synthesize[A: Arbitrary]: Arbitrary[OneAnd[ListWrapper, A]] = implicitly
}

implicit def listWrapperEq[A: Eq]: Eq[ListWrapper[A]] = Eq.by(_.list)
Expand Down
18 changes: 9 additions & 9 deletions tests/src/test/scala/cats/tests/OneAndTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ import cats.laws.discipline.arbitrary.{evalArbitrary, oneAndArbitrary}
import scala.util.Random

class OneAndTests extends CatsSuite {
checkAll("OneAnd[Int, List]", OrderLaws[OneAnd[Int, List]].eqv)
checkAll("OneAnd[List, Int]", OrderLaws[OneAnd[List, Int]].eqv)

// Test instances that have more general constraints
{
implicit val functor = ListWrapper.functor
checkAll("OneAnd[Int, ListWrapper]", FunctorTests[OneAnd[?, ListWrapper]].functor[Int, Int, Int])
checkAll("Functor[OneAnd[A, ListWrapper]]", SerializableTests.serializable(Functor[OneAnd[?, ListWrapper]]))
checkAll("OneAnd[ListWrapper, Int]", FunctorTests[OneAnd[ListWrapper, ?]].functor[Int, Int, Int])
checkAll("Functor[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Functor[OneAnd[ListWrapper, ?]]))
}

{
implicit val monadCombine = ListWrapper.monadCombine
checkAll("OneAnd[Int, ListWrapper]", SemigroupKTests[OneAnd[?, ListWrapper]].semigroupK[Int])
checkAll("OneAnd[Int, List]", GroupLaws[OneAnd[Int, List]].semigroup)
checkAll("SemigroupK[OneAnd[A, ListWrapper]]", SerializableTests.serializable(SemigroupK[OneAnd[?, ListWrapper]]))
checkAll("Semigroup[NonEmptyList[Int]]", SerializableTests.serializable(Semigroup[OneAnd[Int, List]]))
checkAll("OneAnd[ListWrapper, Int]", SemigroupKTests[OneAnd[ListWrapper, ?]].semigroupK[Int])
checkAll("OneAnd[List, Int]", GroupLaws[OneAnd[List, Int]].semigroup)
checkAll("SemigroupK[OneAnd[ListWrapper, A]]", SerializableTests.serializable(SemigroupK[OneAnd[ListWrapper, ?]]))
checkAll("Semigroup[NonEmptyList[Int]]", SerializableTests.serializable(Semigroup[OneAnd[List, Int]]))
}

{
implicit val foldable = ListWrapper.foldable
checkAll("OneAnd[Int, ListWrapper]", FoldableTests[OneAnd[?, ListWrapper]].foldable[Int, Int])
checkAll("Foldable[OneAnd[A, ListWrapper]]", SerializableTests.serializable(Foldable[OneAnd[?, ListWrapper]]))
checkAll("OneAnd[ListWrapper, Int]", FoldableTests[OneAnd[ListWrapper, ?]].foldable[Int, Int])
checkAll("Foldable[OneAnd[ListWrapper, A]]", SerializableTests.serializable(Foldable[OneAnd[ListWrapper, ?]]))
}

{
Expand Down