2013-07-14 41 views
1

假設你有一個看起來像這樣的EitherT:當使用EitherT [StateWithSomeFixedStateType,T,U]時,如何返回左邊時執行一些狀態操作?

type StateListOfString[+T] = State[List[String], T] 
type MyEitherT = EitherT[StateListOfString, Int, Boolean] 

如果你有一個換理解,可以返回左:

my computation = for { 
    a <- thingThatCouldReturnLeft 
    b <- otherThingThatCouldReturnLeft 
} yield b 

你怎麼能跟進一個換理解在它自己返回左邊之前操縱狀態?

我覺得我想要的東西非常接近,否則容易,但否則容易沒有訪問到左邊的值:

def orElse[AA >: A, BB >: B](x: => EitherT[F, AA, BB])(implicit F: Bind[F]): EitherT[F, AA, BB] = { 

如果它採取類似(X:=> INT => EitherT [ F,AA,BB])而不是隻是(x:=> EitherT [F,AA,BB]),它會起作用。

我曾試圖開始:

for { 
    a <- myComputation.isLeft 
    // OK, now I have something sensible, and I can follow up with something like 
    // a leftMap 

但是,如果我通過調用isLeft開始,它看起來像計算運行至少兩次,一次爲isLeft,並且當我再次打電話類似leftMap。

在這裏使用什麼是正確的?

回答

1

綜觀orElse源似乎可以自然地概括爲

import scala.language.higherKinds 

def onLeft[F[+_],A,B](x: => EitherT[F, A, B]) 
        (y: A => EitherT[F, A, B]) 
        (implicit F: Bind[F]): EitherT[F, A, B] = 
{ 
    val g = x.run 
    EitherT(F.bind(g) { 
    case -\/(l) => y(l).run 
    case \/-(_) => g 
    }) 
} 

這基本上是同樣的事情交換左/右,然後用一元結合

def onLeft1[F[+_],A,B](x: => EitherT[F, A, B]) 
         (y: A => EitherT[F, A, B]) 
         (implicit F: Monad[F]): EitherT[F, A, B] = 
    x.swap.flatMap((a: A) => y(a).swap).swap 

但當然第一個變體更有效率(在F中也更加通用一些)。

相關問題