0

There are 2 local methods defined as:

final case class Kleisli[F[_], A, B](run: A => F[B]) { self =>
  ...
  def local[AA](f: AA => A): Kleisli[F, AA, B] =
    Kleisli(f.andThen(run))
  ...
}

and as:

sealed private[data] trait KleisliFunctions {
  ...
  def local[M[_], A, R](f: R => R)(fa: Kleisli[M, R, A]): Kleisli[M, R, A] =
    Kleisli(f.andThen(fa.run))
}

The 2nd one should be used as a factory method, to construct Kleisli.

Can you please offer any usecases to use the 2nd method, defined in KleisliFunctions, to create instance of Kleisli. With an example, if possible. Cannot get it, where this method could be useful.

Alexandr
  • 9,213
  • 12
  • 62
  • 102

2 Answers2

2

For example

val k: Kleisli[Option, String, Char] = Kleisli(_.headOption)

k.local[Int](_.toString): Kleisli[Option, Int, Char]  // Kleisli#local

Kleisli.local((_: String).toUpperCase)(k): Kleisli[Option, String, Char] // KleisliFunctions#local

Object Kleisli extends trait KleisliFunctions.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
2

What I can note is: Kleisli.local(f)(fa) is the same as fa.local(f), but it's both more verbose and strictly less powerful (it requires argument and return type of f to be the same, fa.local(f) doesn't).

A potential reason to use it would be if fa's type needs to be inferred, in which case Kleisli.local provides an expected type and fa.local doesn't.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487