Skip to content

Commit

Permalink
Add Applicative for Arrow (#2078)
Browse files Browse the repository at this point in the history
* Add Apply for Arrow

* Strengthen to Applicative, move to Applicative

Also adds tests

* More tests, explicit wiring for laws check

* Drop doctests
  • Loading branch information
stephen-lazaro authored and kailuowang committed Dec 10, 2017
1 parent 620645d commit b0cf5c0
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
28 changes: 28 additions & 0 deletions core/src/main/scala/cats/Applicative.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cats

import cats.arrow.Arrow
import cats.instances.list._
import simulacrum.typeclass

Expand Down Expand Up @@ -188,8 +189,35 @@ import simulacrum.typeclass
object Applicative {
def monoid[F[_], A](implicit f: Applicative[F], monoid: Monoid[A]): Monoid[F[A]] =
new ApplicativeMonoid[F, A](f, monoid)

/**
* Creates an applicative functor for `F`, holding domain fixed and combining
* over the codomain.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> import cats.Applicative.catsApplicativeForArrow
* scala> val toLong: Int => Long = _.toLong
* scala> val double: Int => Int = 2*_
* scala> val f: Int => (Long, Int) = catsApplicativeForArrow.product(toLong, double)
* scala> f(3)
* res0: (Long, Int) = (3,6)
* }}}
*/
implicit def catsApplicativeForArrow[F[_, _], A](implicit F: Arrow[F]): Applicative[F[A, ?]] =
new ArrowApplicative[F, A](F)
}

private[cats] class ApplicativeMonoid[F[_], A](f: Applicative[F], monoid: Monoid[A]) extends ApplySemigroup(f, monoid) with Monoid[F[A]] {
def empty: F[A] = f.pure(monoid.empty)
}

private[cats] class ArrowApplicative[F[_, _], A](F: Arrow[F]) extends Applicative[F[A, ?]] {
def pure[B](b: B): F[A, B] = F.lift[A, B](_ => b)
override def map[B, C](fb: F[A, B])(f: B => C): F[A, C] = F.rmap(fb)(f)
def ap[B, C](ff: F[A, B => C])(fb: F[A, B]): F[A, C] =
F.rmap(F.andThen(F.lift((x: A) => (x, x)), F.split(ff, fb)))(tup => tup._1(tup._2))
override def product[B, C](fb: F[A, B], fc: F[A, C]): F[A, (B, C)] =
F.andThen(F.lift((x: A) => (x, x)), F.split(fb, fc))
}
4 changes: 4 additions & 0 deletions tests/src/test/scala/cats/tests/FunctionSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class FunctionSuite extends CatsSuite {
}
}

// Test for Arrow applicative
Applicative[String => ?]
checkAll("Function1[String, ?]",
ApplicativeTests[Function1[String, ?]](Applicative.catsApplicativeForArrow[Function1, String]).applicative[Int, Int, Int])

// serialization tests for the various Function0-related instances
checkAll("Eq[() => Eqed]", SerializableTests.serializable(Eq[() => Eqed]))
Expand Down

0 comments on commit b0cf5c0

Please sign in to comment.