简体   繁体   English

如何在Scala猫中的monad变换器堆栈顶部定义本地方法

[英]How to define local method on top of a monad transformer stack in Scala cats

I have a monad transformer stack on top of a Kleisli defined as: 我在Kleisli上面有一个monad变换器堆栈,定义如下:

type Env = Map[String,Int]
type MyState = List[Int]
type S[A] = EitherT[StateT[WriterT[Kleisli[List,Env,?],String,?],MyState,?], String, A]

and I want to define a local method with the following signature: 我想用以下签名定义一个local方法:

def localE[A](f: Env => Env)(sa: S[A]): S[A] = ???

Is it possible? 可能吗?

I know that there is a local method in MonadReader with the signature: 我知道MonadReader中有一个带签名的local方法:

def local[A](f: R => R)(fa: F[A]): F[A]

So the simplest solution would be to obtain the MonadReader implicit from S , however, I could not find how to do it. 因此,最简单的解决方案是从S隐式获取MonadReader ,但是,我找不到如何做到这一点。

A simple snippet of my code would be the following: 我的代码的简单片段如下:

package examples
import cats._, data._
import cats.implicits._

object local {
 type Env = Map[String,Int]
 type MyState = List[Int]
 type S[A] = EitherT[StateT[WriterT[Kleisli[List,Env,?],String,?],MyState,?], String, A]

 // The following definition doesn't compile
 // implicit lazy val mr = MonadReader[S,Env]

 // Modify the environment
 def localE[A](f: Env => Env)(sa: S[A]): S[A] = ???
}

A possible solution is to unlift the monad stack manually. 一种可能的解决方案是手动unlift monad堆栈。 In this case, I defined the following two auxiliary functions: 在这种情况下,我定义了以下两个辅助功能:

  def localW[A](f: Env => Env)
               (c: WriterT[Kleisli[List,Env,?],String,A]): 
         WriterT[Kleisli[List,Env,?],String,A] = {
   type WriterTF[F[_],A] = WriterT[F, String, A]
   val r: WriterT[Kleisli[List,Env,?],String,(String,A)] = 
      c.run.local(f).liftT[WriterTF]
   r.mapBoth { case (_, (w, x)) => (w, x) }
 }

   def localS[A](f: Env => Env)
                (c: StateT[WriterT[Kleisli[List,Env,?],String,?],MyState,A]): 
        StateT[WriterT[Kleisli[List,Env,?],String,?],MyState,A] = {
  StateT(s => localW(f)(c.run(s)))
  }

And the local function can be defined as: 并且本地函数可以定义为:

  def localE[A](f: Env => Env)(sa: S[A]): S[A] = {
     EitherT(localS(f)(sa.value))
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM