2016-09-01 6 views
1

스칼라 고양이의 모나드 변압기 스택의 상단에 현지 방법을 정의 :어떻게로 정의 된 Kleisli의 상단에 모나드 변압기 스택이

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

을 나는 다음과 local 방법을 정의 할 서명 :

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

가능합니까?

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

그래서 가장 간단한 해결책은하지만, 내가 그것을 수행하는 방법을 찾을 수 없습니다, S에서 MonadReader 암시를 얻을 것이다 :

는 내가 서명 MonadReaderlocal 방법이 있다는 것을 알고있다.

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] = ??? 
} 

답변

0

가능한 솔루션을 수동으로 unlift 모나드 스택입니다 :

내 코드의 간단한 조각은 다음과 같은 것이다.

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))) 
    } 

로컬 함수로 정의 될 수있다 :

def localE[A](f: Env => Env)(sa: S[A]): S[A] = { 
    EitherT(localS(f)(sa.value)) 
    } 
이때, I는 다음의 두 가지 기능을 보조 정의한