Skip to content

Commit

Permalink
Add Strong and Arrow instances for IRWST
Browse files Browse the repository at this point in the history
  • Loading branch information
Itamar Ravid committed Sep 10, 2017
1 parent 8b99340 commit b864100
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 2 deletions.
52 changes: 51 additions & 1 deletion core/src/main/scala/cats/data/ReaderWriterStateT.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package cats
package data

import cats.functor.{ Bifunctor, Contravariant, Profunctor }
import cats.functor.{ Bifunctor, Contravariant, Profunctor, Strong }
import cats.arrow.Arrow
import cats.syntax.either._

/**
Expand Down Expand Up @@ -442,6 +443,11 @@ private[data] sealed abstract class IRWSTInstances1 extends IRWSTInstances2 {
implicit def F: Monad[F] = F0
implicit def L: Monoid[L] = L0
}

implicit def catsDataStrongForIRWST[F[_], E, L, T](implicit F0: Monad[F]): Strong[IndexedReaderWriterStateT[F, E, L, ?, ?, T]] =
new IRWSTStrong[F, E, L, T] {
implicit def F: Monad[F] = F0
}
}

private[data] sealed abstract class IRWSTInstances2 extends IRWSTInstances3 {
Expand All @@ -452,6 +458,13 @@ private[data] sealed abstract class IRWSTInstances2 extends IRWSTInstances3 {
implicit def F: Monad[F] = FM
implicit def L: Monoid[L] = L0
}

implicit def catsDataArrowForIRWST[F[_], E, L, T](implicit F0: Monad[F], L0: Monoid[L], T0: Monoid[T]): Arrow[IndexedReaderWriterStateT[F, E, L, ?, ?, T]] =
new IRWSTArrow[F, E, L, T] {
implicit def F: Monad[F] = F0
implicit def L: Monoid[L] = L0
implicit def T: Monoid[T] = T0
}
}

private[data] sealed abstract class IRWSTInstances3 {
Expand Down Expand Up @@ -489,6 +502,43 @@ private[data] sealed abstract class IRWSTProfunctor[F[_], E, L, T] extends Profu
fab.dimap(f)(g)
}

private[data] sealed abstract class IRWSTStrong[F[_], E, L, T] extends IRWSTProfunctor[F, E, L, T] with Strong[IndexedReaderWriterStateT[F, E, L, ?, ?, T]] {
implicit def F: Monad[F]

def first[A, B, C](fa: IndexedReaderWriterStateT[F, E, L, A, B, T]): IndexedReaderWriterStateT[F, E, L, (A, C), (B, C), T] =
IndexedReaderWriterStateT { case (e, (a, c)) =>
F.map(fa.run(e, a)) { case (l, b, t) =>
(l, (b, c), t)
}
}

def second[A, B, C](fa: IndexedReaderWriterStateT[F, E, L, A, B, T]): IndexedReaderWriterStateT[F, E, L, (C, A), (C, B), T] =
first(fa).dimap((_: (C, A)).swap)(_.swap)
}

private[data] sealed abstract class IRWSTArrow[F[_], E, L, T] extends IRWSTStrong[F, E, L, T] with Arrow[IndexedReaderWriterStateT[F, E, L, ?, ?, T]] {
implicit def F: Monad[F]
implicit def T: Monoid[T]
implicit def L: Monoid[L]

def lift[A, B](f: A => B): IndexedReaderWriterStateT[F, E, L, A, B, T] =
IndexedReaderWriterStateT { (e, a) =>
F.pure((L.empty, f(a), T.empty))
}

def id[A]: IndexedReaderWriterStateT[F, E, L, A, A, T] =
IndexedReaderWriterStateT.pure(T.empty)

def compose[A, B, C](f: IndexedReaderWriterStateT[F, E, L, B, C, T], g: IndexedReaderWriterStateT[F, E, L, A, B, T]): IndexedReaderWriterStateT[F, E, L, A, C, T] =
IndexedReaderWriterStateT { (e, a) =>
F.flatMap(g.run(e, a)) { case (la, b, ta) =>
F.map(f.run(e, b)) { case (lb, c, tb) =>
(L.combine(la, lb), c, T.combine(ta, tb))
}
}
}
}

private[data] sealed abstract class IRWSTBifunctor[F[_], E, L, SA] extends Bifunctor[IndexedReaderWriterStateT[F, E, L, SA, ?, ?]] {
implicit def F: Functor[F]

Expand Down
13 changes: 12 additions & 1 deletion tests/src/test/scala/cats/tests/ReaderWriterStateTTests.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package cats
package tests

import cats.arrow.Arrow
import cats.data.{ IRWST, IndexedReaderWriterStateT, ReaderWriterStateT, ReaderWriterState, EitherT }
import cats.functor.{ Contravariant, Bifunctor, Profunctor }
import cats.functor.{ Contravariant, Bifunctor, Profunctor, Strong }
import cats.laws.discipline._
import cats.laws.discipline.eq._
import cats.laws.discipline.arbitrary._
Expand Down Expand Up @@ -322,6 +323,16 @@ class ReaderWriterStateTTests extends CatsSuite {
checkAll("Profunctor[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]",
SerializableTests.serializable(Profunctor[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]))

checkAll("IndexedReaderWriterStateT[ListWrapper, String, String, Int, String, Int]",
StrongTests[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]].strong[Int, Int, Int, String, String, String])
checkAll("Strong[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]",
SerializableTests.serializable(Strong[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]))

checkAll("IndexedReaderWriterStateT[ListWrapper, String, String, Int, String, Int]",
ArrowTests[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]].arrow[Int, Int, Int, String, String, String])
checkAll("Arrow[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]",
SerializableTests.serializable(Arrow[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]))

checkAll("IndexedReaderWriterStateT[ListWrapper, String, String, Int, Int, String]",
BifunctorTests[IndexedReaderWriterStateT[ListWrapper, String, String, Int, ?, ?]].bifunctor[Int, Int, Int, String, String, String])
checkAll("Bifunctor[IndexedReaderWriterStateT[ListWrapper, String, String, Int, ?, ?]]",
Expand Down

0 comments on commit b864100

Please sign in to comment.