2015-10-23 3 views
1

У меня есть тип, форма, как это:Элегантный Перевалка Скала будущего [Либо]]

val myType: Future[Either[MyError, TypeA]] = // some value 

Я знаю, что я мог бы матч узор на это и получить вправо или влево типа, но проблема заключается в том, что мне пришлось бы вложить логику соответствия шаблону. Я ищу гораздо более элегантный способ справиться с этим? Какие-либо предложения?

+1

Это звучит, как вам нужно монады трансформаторы, которые, к сожалению, Ядро scala не обеспечивает. Сопоставимый тип в scalaz будет «EitherT [Task, MyError, TypeA]». Вы можете делать такие операции, как 'map',' flatMap' и т. Д., Что разумно. –

+0

Нет! использование scalaz не является вариантом для этого проекта! – sparkr

+0

Вы не можете добавить зависимости? Думаю, вы могли бы свернуть свой «EitherT»? –

ответ

6

Если закодировать ваш MyError как исключение, вы не нуждаетесь в Either больше и может просто patternMatch против завершения, или использовать recoverWith для отображения его на другой тип:

myType.onComplete { 
    case Success(t) => 
    case Failure(e) => 
} 

для размещения на карте существующих Either типов вы могли бы сделать что-то вроде этого:

case class MyException(e: MyError) extends Exception 

def eitherToException[A](f: Future[Either[MyError,A]]): Future[A] = { 
    f.flatMap { 
    case Left(e) => Future.failed(MyException(e)) 
    case Right(x) => Future.successful(x) 
    } 
} 

val myType2 = eitherToException(myType) 

в качестве альтернативы, если MyError и TypeA находятся под вашим контролем, вы можете созд ели общий супер типа и сопоставление с образцом, что:

sealed trait MyResult 
final case class MyError() extends MyResult 
final case class TypeA() extends MyResult 

myType.map { 
    case MyError() => ... 
    case TypeA() => ... 
} 
+0

Нет! наличие MyResult как супер-типа не работает, и я не считаю его полезным использовать наследование ради него! TypeA был всего лишь одним примером. Поскольку все мои методы обслуживания возвращают Либо с MyError или соответствующий тип класса case, который обрабатывает метод обслуживания! – sparkr

+1

Я думаю, что самым элегантным решением является приложение myFuture.onComplete и исключение MyError. Это имеет смысл, он работает, он изящный. Комментарий в сторону, @sparkr проверить свои манеры. –

+0

@Arne: Спасибо за сообщение, но меня очень раздражало использование бессмысленной структуры наследования во имя шаблона Cake, где наследующий класс и унаследованный класс вообще не имеют отношения! Извините, если я был невежливым! – sparkr

1

Вы можете создавать пользовательские экстрактор объекты:

object FullSuccess { 
    def unapply[T](x: Try[Either[MyError, T]]) = x match { 
    case Success(Right(x)) => Some(x) 
    case _ => None 
    } 
} 

object PartSuccess { 
    def unapply[T](x: Try[Either[MyError, T]]) = x match { 
    case Success(Left(err)) => Some(err) 
    case _ => None 
    } 
} 

И

val myType: Future[Either[MyError, TypeA]] = // some value 

myType.onComplete { 
    case FullSuccess(x) => ... // equivalent to case Success(Right(x)) 
    case PartSuccess(x) => ... // equivalent to case Success(Left(x)) 
    case Failure(e) => ... 
}