Skip to content

Commit

Permalink
Merge pull request #886 from pvillega/master
Browse files Browse the repository at this point in the history
Add map method to OneAnd. Fix for #885
  • Loading branch information
julien-truffaut committed Feb 17, 2016
2 parents ce94b7f + 5e26a01 commit 8c35756
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 5 deletions.
16 changes: 11 additions & 5 deletions core/src/main/scala/cats/data/OneAnd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package data

import scala.annotation.tailrec
import scala.collection.mutable.ListBuffer
import cats.std.list._

/**
* A data type which represents a single element (head) and some other
Expand Down Expand Up @@ -65,6 +66,12 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
def foldRight[B](lb: Eval[B])(f: (A, Eval[B]) => Eval[B])(implicit F: Foldable[F]): Eval[B] =
Eval.defer(f(head, F.foldRight(tail, lb)(f)))

/**
* Applies f to all the elements of the structure
*/
def map[B](f: A => B)(implicit F: Functor[F]): OneAnd[F, B] =
OneAnd(f(head), F.map(tail)(f))

/**
* Typesafe equality operator.
*
Expand Down Expand Up @@ -104,7 +111,7 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 {
}

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

implicit def oneAndReducible[F[_]](implicit F: Foldable[F]): Reducible[OneAnd[F, ?]] =
new NonEmptyReducible[OneAnd[F,?], F] {
Expand All @@ -114,7 +121,7 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 {
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))
fa map f

def pure[A](x: A): OneAnd[F, A] =
OneAnd(x, monad.empty)
Expand All @@ -133,7 +140,6 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 {
trait OneAndLowPriority0 {
implicit val nelComonad: Comonad[OneAnd[List, ?]] =
new Comonad[OneAnd[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 {
Expand All @@ -147,15 +153,15 @@ trait OneAndLowPriority0 {
fa.head

def map[A, B](fa: OneAnd[List, A])(f: A => B): OneAnd[List, B] =
OneAnd(f(fa.head), fa.tail.map(f))
fa 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[F, A])(f: A => B): OneAnd[F, B] =
OneAnd(f(fa.head), F.map(fa.tail)(f))
fa map f
}

}
Expand Down
7 changes: 7 additions & 0 deletions tests/src/test/scala/cats/tests/OneAndTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,11 @@ class OneAndTests extends CatsSuite {
nel.forall(p) should === (list.forall(p))
}
}

test("NonEmptyList#map is consistent with List#map") {
forAll { (nel: NonEmptyList[Int], p: Int => String) =>
val list = nel.unwrap
nel.map(p).unwrap should === (list.map(p))
}
}
}

0 comments on commit 8c35756

Please sign in to comment.