1

Есть ли способ привязать значение Either[L1, R1] к функции типа R1 => Either[L2, R2] и получить значение Either[L1 | L2, R2], чтобы отдельные функции могли объявлять и, возможно, возвращать свои ошибки и потребителей монадический конвейер этих функций может полностью обрабатывать все возможные ошибки с помощью исчерпывающего, безопасного типа?Создание объединения в левой части любого типа

Редактировать

Вот пример ...

sealed trait IncrementError 
case object MaximumValueReached extends IncrementError 

def increment(n: Int): Either[IncrementError, Int] = n match { 
    case Integer.MAX_VALUE => Left(MaximumValueReached) 
    case n => Right(n + 1) 
} 

sealed trait DecrementError 
case object MinimumValueReached extends DecrementError 

def decrement(n: Int): Either[DecrementError, Int] = n match { 
    case Integer.MIN_VALUE => Left(MinimumValueReached) 
    case n => Right(n - 1) 
} 

for { 
    n <- increment(0).right 
    n <- decrement(n).right 
} yield n // scala.util.Either[Object, Int] = Right(0) 

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

val n = for { 
    n <- increment(0).right 
    n <- decrement(n).right 
} yield n // scala.util.Either[IncrementError | DecrementError, Int] 

match n { 
    case Left(MaximumValueReached) => println("Maximum value reached!") 
    case Left(MinimumValueReached) => println("Minimum value reached!") 
    case Right(_) => println("Success!") 
} 
+0

Стандарт 'Either' позволяет вам отображать/flatMap только в необъективном виде, преобразовывая его в' LeftProjection' или 'RightProjection'. Это не так удобно, как вам хотелось бы в вашем предположении, но на самом деле вполне работоспособным :) –

+0

Что вы подразумеваете под 'L1 | L2'? Вы можете использовать правую проекцию, но тип результата будет «[LC, RC]», где, например, 'LC' является ближайшим общим предком' L1' и 'L2'. Это то, чего вы ожидаете? –

+0

@AlexanderArendar Есть ли что-нибудь в Scalaz или Cats, которые поддерживают это поведение? –

ответ

0

Я хотел бы сделать следующее:

/** 
    * Created by alex on 10/3/16. 
    */ 
object Temp{ 
    sealed trait IncrementError 
    case object MaximumValueReached extends IncrementError 
    sealed trait DecrementError 
    case object MinimumValueReached extends DecrementError 

    type MyResult = Either[Either[IncrementError, DecrementError], Int] 

    def increment(n: Int): MyResult = n match { 
    case Integer.MAX_VALUE => Left(Left(MaximumValueReached)) 
    case n => Right(n + 1) 
    } 

    def decrement(n: Int): MyResult = n match { 
    case Integer.MIN_VALUE => Left(Right(MinimumValueReached)) 
    case n => Right(n - 1) 
    } 

    def main(args:Array[String]) = { 
    val result = for { 
     k <- increment(0).right 
     n <- decrement(k).right 
    } yield n 

    result match { 
     case Left(Left(MaximumValueReached)) => println("Maximum value reached!") 
     case Left(Right(MinimumValueReached)) => println("Minimum value reached!") 
     case Right(_) => println("Success!") 
    } 
    } 
} 

Честно говоря, я не люблю его, но он работает в том случае, если вы не 't хотите иметь IncrementError и DecrementError, чтобы наследовать от некоторых признаков предка по некоторым причинам.

 Смежные вопросы

  • Нет связанных вопросов^_^