2013-07-24 27 views
17

Farklı arka uç sistemlerine çok sayıda çağrı yapan ve arka uç sistemlerde işlem akışını basitleştirmek için anlaşmaları kullanmayı ümit eden bir uygulamam var.EitherT ve Geleni Birleştirme

EitherT (scalaz) ve Future (scala 2.10) birleştirmeyi düşünüyorum, böylece ilk potansiyel hatayı (gelecekteki veya arka uç sistem sorununda) yakalayabilir ve son kullanıcıya uygun bir ileti döndürebilirim. Hızlı bir scalaz Doğrulama baktım ama ilk hata yakalama ve tüm hatalar için tavsiye EitherT kullanmaktır.

Ben ancak aşağıdaki hatayı alıyorum, ilk Repl içinde basit bir örnek çalışıyorum

hatası: scalaz.Functor [scala.concurrent.Future]

: Parametre F örtülü değeri bulamadı
import scala.concurrent._ 
import scalaz._ 
import Scalaz._ 
import ExecutionContext.Implicits.global 

type EitherFuture[+A] = EitherT[Future, String, A] 

def method1Success : EitherFuture[Int] = { 
    println("method 1 success") 
    EitherT { 
    Future { 
     1.right 
    } 
    } 
} 

def method2Failure : EitherFuture[Int] = { 
    println("method 2 failure") 
    EitherT { 
    Future { 
     "fail".left 
    } 
    } 
} 

val m1 = method1Success 

// problem 
m1.isRight 

// problem 
def methodChain1 = { 
    for { 
    a <- method1Success 
    b <- method2Failure 
    } yield b 
} 

Her iki scala ve scalaz için hala yeniyim, böylece herhangi bir işaretçi harika olur.

** @stew öneri göre scalaz-contrib dahil ederek Güncelleme **

şimdilik-comprehensions EitherT ve Geleceğin farklı basit kullanım durumları arka uç başarısını gösteren kombine bir arka uca sahip gösteren güncel sürümüne sahip

def isRight(implicit F: Functor[F]): F[Boolean] 

It: EitherT üzerinde tanımlı isRight imzasıyla birlikte başarısızlık ve gelecekteki hata

import scala.concurrent._ 
import scalaz._ 
import Scalaz._ 
import ExecutionContext.Implicits.global 
import scalaz.contrib._ 
import scalaz.contrib.std._ 
import scala.concurrent.duration._ 

type EitherFuture[+A] = EitherT[Future, String, A] 

// various methods that mimic success or different failures 
def methodBackendSuccess : EitherFuture[Int] = { 
    println("method backend success") 
    EitherT { 
    Future {1.right} 
    } 
} 

def methodBackendFailure : EitherFuture[Int] = { 
    println("method backend failure") 
    EitherT { 
    Future { "fail".left} 
    } 
} 

def methodFutureFailure : EitherFuture[Int] = { 
    println("method future failure") 
    EitherT { 
    Future.failed(new Exception("future failed")) 
    } 
} 

// different combinations for for-comprehensions 
def methodChainBackendSuccess = { 
    for { 
    a <- methodBackendSuccess 
    b <- methodBackendSuccess 
    c <- methodBackendSuccess 
    } yield c 
} 

def methodChainBackendFailure = { 
    for { 
    a <- methodBackendSuccess 
    b <- methodBackendFailure 
    c <- methodBackendSuccess 
    } yield c 
} 

def methodChainFutureFailure = { 
    for { 
    a <- methodBackendSuccess 
    b <- methodFutureFailure 
    c <- methodBackendSuccess 
    } yield c 
} 

// process results for different chain methods 
def processOutcome(chainMethod: => EitherFuture[Int]):Int = try { 
    val x = Await.result(chainMethod.run, 30 seconds) 
    x.toEither match {        
     case Left(l) => { 
     println("Backend failure <" + l + ">") 
     -1 
     } 
     case Right(r) => { 
     println("Backend success <" + r + ">") 
     r 
     } 
    } 
    } catch { 
    case e: Exception => { 
     println("Future error <" + e.getMessage + ">") 
     -99 
    } 
} 

// run tests 
val backendSuccess = processOutcome(methodChainBackendSuccess) 
val backendFailure = processOutcome(methodChainBackendFailure) 
val futureFailure = processOutcome(methodChainFutureFailure) 
+0

"Her iki" işine ihtiyacınız olduğuna emin misiniz? 'Gelecek' zaten başarısızlığı modelleyebilir ve sıralama yapmak istediğiniz davranışa sahiptir. –

+0

Merhaba @TravisBrown Hala başıma scala yiyorum, bu yüzden ihtiyacım olan şey doğru olabilir, arka uç başarısı, arka uç hatası ve gelecekteki bir başarısızlık yakalama ve bunları farklı şekilde ele alma yeteneğidir. Çalıştığım bazı kodlar var, orjinal soruyu güncelleyeceğim ve belki de bir EitherT ve Geleceğe ihtiyaç duyup duymadığımı açıklığa kavuşturabilirim. –

+1

Beni bir süredir götüren bir şey: Functor [Gelecek], yalnızca örtük bir yürütme konteksti kapsamındaysa bulunabilir – cvogt

cevap

6

Gelecek için bir Functor örneği almanız veya sağlamanız gerekir. scalaz-contrib projesinden birini kullanmanızı öneriyorum. -contrib, scalaz üzerinde çalışan aynı insanlar tarafından üzerinde çalışılan ayrı bir projedir. Gelecek örnekleri scalaz-core yerine bu pakette bulunuyor, çünkü şimdilik scalaz-core, scala 2.9 ve 2.10 arasındaki uyumluluğu koruyor.

+0

Build.scala dosyama "org.typelevel" %% "scalaz-contrib-210"% "% 0.1.4" 'ekleyerek çalışmam için örneğimi güncelleyebildim, orjinal soruyu kodu. –

1

Bak Gelecekte, EitherT'inizin type parametresiyle parametrelenmiş bir Functor beklemektedir. Scalaz tipi Gelecek için örtük bir funktor sağlamaz, kendi şu bu modeli yazmak gerekir: Desteklenen her türü için

http://scalaz.github.io/scalaz/scalaz-2.9.0-1-6.0/doc.sxr/scalaz/Functor.scala.html

Bildirimi tüm örtük defs.

+1

Eğer Scalaz 6 kullanıyor olsaydım, 'implicit def FutureFunctor: Functor [Future] = yeni Functor [Future] { def fmap [A, B] (t: Future [A], f: A => B): Gelecek [B] = t haritası f } 'Maalesef Scalaz 7 ile çalışıyorum ve örtülü kusurlar değişmiş gibiydi. Scalaz7'ye benzer bir şey yapmak için nereye bakmalıyım? –

İlgili konular