Skip to content

Commit

Permalink
Merge pull request #598 from ceedubs/oneand-type-params
Browse files Browse the repository at this point in the history
Swap type parameter order in OneAnd
  • Loading branch information
adelbertc committed Nov 4, 2015
2 parents 0bd5e0b + 1ee2130 commit 8e1214d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 49 deletions.
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

0 comments on commit 8e1214d

Please sign in to comment.