Skip to content

Commit 94f4928

Browse files
author
LukaJCB
authored
Finish adding mapK (#2000)
* Add mapK to most (hopefully all) transformers * Add mapK to free related constructs * Deprecate Kleisli#transform in favor of mapK * Fix tests file name * Add missing mapK methods * Don't deprecate Free methods and use mapK for parallel kleisli instance
1 parent f3981dd commit 94f4928

25 files changed

+193
-40
lines changed

core/src/main/scala/cats/data/EitherK.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ final case class EitherK[F[_], G[_], A](run: Either[F[A], G[A]]) {
1616
def map[B](f: A => B)(implicit F: Functor[F], G: Functor[G]): EitherK[F, G, B] =
1717
EitherK(run.bimap(F.lift(f), G.lift(f)))
1818

19+
/**
20+
* Modify the right side context `G` using transformation `f`.
21+
*/
22+
def mapK[H[_]](f: G ~> H): EitherK[F, H, A] =
23+
EitherK(run.map(f.apply))
24+
1925
def coflatMap[B](f: EitherK[F, G, A] => B)(implicit F: CoflatMap[F], G: CoflatMap[G]): EitherK[F, G, B] =
2026
EitherK(
2127
run.bimap(a => F.coflatMap(a)(x => f(leftc(x))), a => G.coflatMap(a)(x => f(rightc(x))))
@@ -234,4 +240,3 @@ private[data] trait EitherKComonad[F[_], G[_]] extends Comonad[EitherK[F, G, ?]]
234240
def extract[A](p: EitherK[F, G, A]): A =
235241
p.extract
236242
}
237-

core/src/main/scala/cats/data/EitherT.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
9191

9292
def map[D](f: B => D)(implicit F: Functor[F]): EitherT[F, A, D] = bimap(identity, f)
9393

94+
/**
95+
* Modify the context `F` using transformation `f`.
96+
*/
97+
def mapK[G[_]](f: F ~> G): EitherT[G, A, B] = EitherT[G, A, B](f(value))
98+
9499
def semiflatMap[D](f: B => F[D])(implicit F: Monad[F]): EitherT[F, A, D] =
95100
flatMap(b => EitherT.right(f(b)))
96101

core/src/main/scala/cats/data/Func.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ sealed abstract class Func[F[_], A, B] { self =>
1212
def run: A => F[B]
1313
def map[C](f: B => C)(implicit FF: Functor[F]): Func[F, A, C] =
1414
Func.func(a => FF.map(self.run(a))(f))
15+
16+
/**
17+
* Modify the context `F` using transformation `f`.
18+
*/
19+
def mapK[G[_]](f: F ~> G): Func[G, A, B] =
20+
Func.func(run andThen f.apply)
1521
}
1622

1723
object Func extends FuncInstances {

core/src/main/scala/cats/data/IdT.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ final case class IdT[F[_], A](value: F[A]) {
99
def map[B](f: A => B)(implicit F: Functor[F]): IdT[F, B] =
1010
IdT(F.map(value)(f))
1111

12+
/**
13+
* Modify the context `F` using transformation `f`.
14+
*/
15+
def mapK[G[_]](f: F ~> G): IdT[G, A] =
16+
IdT[G, A](f(value))
17+
1218
def flatMap[B](f: A => IdT[F, B])(implicit F: FlatMap[F]): IdT[F, B] =
1319
IdT(F.flatMap(value)(f.andThen(_.value)))
1420

core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ final class IndexedReaderWriterStateT[F[_], E, L, SA, SB, A](val runF: F[(E, SA)
5252
def map[B](f: A => B)(implicit F: Functor[F]): IndexedReaderWriterStateT[F, E, L, SA, SB, B] =
5353
transform { (l, s, a) => (l, s, f(a)) }
5454

55+
/**
56+
* Modify the context `F` using transformation `f`.
57+
*/
58+
def mapK[G[_]](f: F ~> G)(implicit F: Functor[F]): IndexedReaderWriterStateT[G, E, L, SA, SB, A] =
59+
IndexedReaderWriterStateT.applyF(
60+
f(F.map(runF)(rwsa => (e, sa) => f(rwsa(e, sa)))))
61+
5562
/**
5663
* Modify the resulting state using `f` and the resulting value using `g`.
5764
*/

core/src/main/scala/cats/data/IndexedStateT.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ final class IndexedStateT[F[_], SA, SB, A](val runF: F[SA => F[(SB, A)]]) extend
3939
def map[B](f: A => B)(implicit F: Functor[F]): IndexedStateT[F, SA, SB, B] =
4040
transform { case (s, a) => (s, f(a)) }
4141

42+
/**
43+
* Modify the context `F` using transformation `f`.
44+
*/
45+
def mapK[G[_]](f: F ~> G)(implicit F: Functor[F]): IndexedStateT[G, SA, SB, A] =
46+
IndexedStateT.applyF(
47+
f(F.map(runF)(_.andThen(fsa => f(fsa)))))
48+
4249
def contramap[S0](f: S0 => SA)(implicit F: Functor[F]): IndexedStateT[F, S0, SB, A] =
4350
IndexedStateT.applyF {
4451
F.map(runF) { safsba =>

core/src/main/scala/cats/data/Kleisli.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ final case class Kleisli[F[_], A, B](run: A => F[B]) { self =>
2121
def mapF[N[_], C](f: F[B] => N[C]): Kleisli[N, A, C] =
2222
Kleisli(run andThen f)
2323

24+
/**
25+
* Modify the context `F` using transformation `f`.
26+
*/
27+
def mapK[G[_]](f: F ~> G): Kleisli[G, A, B] =
28+
Kleisli[G, A, B](run andThen f.apply)
29+
2430
def flatMap[C](f: B => Kleisli[F, A, C])(implicit F: FlatMap[F]): Kleisli[F, A, C] =
2531
Kleisli((r: A) => F.flatMap[B, C](run(r))((b: B) => f(b).run(r)))
2632

@@ -48,8 +54,9 @@ final case class Kleisli[F[_], A, B](run: A => F[B]) { self =>
4854
def local[AA](f: AA => A): Kleisli[F, AA, B] =
4955
Kleisli(f.andThen(run))
5056

57+
@deprecated("Use mapK", "1.0.0")
5158
def transform[G[_]](f: FunctionK[F, G]): Kleisli[G, A, B] =
52-
Kleisli(a => f(run(a)))
59+
mapK(f)
5360

5461
def lower(implicit F: Applicative[F]): Kleisli[F, A, F[B]] =
5562
Kleisli(a => F.pure(run(a)))
@@ -148,10 +155,10 @@ private[data] sealed abstract class KleisliInstances1 extends KleisliInstances2
148155
def monad: Monad[Kleisli[M, A, ?]] = catsDataMonadForKleisli
149156

150157
def sequential: Kleisli[F, A, ?] ~> Kleisli[M, A, ?] =
151-
λ[Kleisli[F, A, ?] ~> Kleisli[M, A, ?]](_.transform(P.sequential))
158+
λ[Kleisli[F, A, ?] ~> Kleisli[M, A, ?]](_.mapK(P.sequential))
152159

153160
def parallel: Kleisli[M, A, ?] ~> Kleisli[F, A, ?] =
154-
λ[Kleisli[M, A, ?] ~> Kleisli[F, A, ?]](_.transform(P.parallel))
161+
λ[Kleisli[M, A, ?] ~> Kleisli[F, A, ?]](_.mapK(P.parallel))
155162
}
156163
}
157164

core/src/main/scala/cats/data/Nested.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@ package data
2323
* res1: List[Option[String]] = List(Some(2), None)
2424
* }}}
2525
*/
26-
final case class Nested[F[_], G[_], A](value: F[G[A]])
26+
final case class Nested[F[_], G[_], A](value: F[G[A]]) {
27+
28+
/**
29+
* Modify the context `F` using transformation `f`.
30+
*/
31+
def mapK[H[_]](f: F ~> H): Nested[H, G, A] =
32+
Nested(f(value))
33+
34+
}
2735

2836
object Nested extends NestedInstances
2937

core/src/main/scala/cats/data/OneAnd.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
7676
def map[B](f: A => B)(implicit F: Functor[F]): OneAnd[F, B] =
7777
OneAnd(f(head), F.map(tail)(f))
7878

79+
/**
80+
* Modify the context `F` using transformation `f`.
81+
*/
82+
def mapK[G[_]](f: F ~> G): OneAnd[G, A] =
83+
OneAnd(head, f(tail))
84+
7985
/**
8086
* Typesafe equality operator.
8187
*

core/src/main/scala/cats/data/OptionT.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
2828
def map[B](f: A => B)(implicit F: Functor[F]): OptionT[F, B] =
2929
OptionT(F.map(value)(_.map(f)))
3030

31+
/**
32+
* Modify the context `F` using transformation `f`.
33+
*/
34+
def mapK[G[_]](f: F ~> G): OptionT[G, A] = OptionT[G, A](f(value))
35+
3136
def semiflatMap[B](f: A => F[B])(implicit F: Monad[F]): OptionT[F, B] =
3237
flatMap(a => OptionT.liftF(f(a)))
3338

0 commit comments

Comments
 (0)