2016-06-20 8 views
2

Это является продолжением до моего предыдущего question:Как реорганизовать функцию, которая бросает исключения с Scalaz или Cats

Пусть я рефакторинга такую ​​функцию:

def check(ox: Option[Int]): Unit = ox match { 
    case None => throw new Exception("X is missing") 
    case Some(x) if x < 0 => throw new Exception("X is negative") 
    case _ =>() 
} 

Я пишу новая чистая функция doCheck, чтобы вернуть либо Unit, либо исключение.

case class MissingX() extends Exception("X is missing") 
case class NegativeX(x: Int) extends Exception(s"$x is negative") 

import scalaz._, Scalaz._ 

type Result[A] = Excepiton \/ A 

def doCheck(ox:Option[Int]): Result[Unit] = for { 
    x <- ox toRightDisjunction MissingX() 
    _ <- (x >= 0) either(()) or NegativeX(x) 
} yield() 

, а затем вызвать его из check

def check(ox:Option[Int]): Unit = doCheck(ox) match { 
    case -\/(e) => throw e 
    case _ =>() 
} 

ли смысл? Было бы лучше реализовать doCheck?

def doCheck(ox:Option[Int]): Result[Int] = for { 
    x1 <- ox toRightDisjunction MissingX() 
    x2 <- (x1 >= 0) either(x1) or NegativeX(x1) 
} yield x2 

Как реализовать это с cats?

+0

Почему вы до сих пор бросить исключение в 'check'? –

+0

@PeterNeyens Я не хочу менять весь код вне 'check'. – Michael

ответ

2

Вы бы сделали почти то же самое в кошках, только у самих кошек нет синтаксиса Boolean => Xor[A, B], как either() or() от scalaz.

import cats.data.Xor 
import cats.implicits._ 

def doCheck(ox: Option[Int]): Xor[Exception, Unit] = 
    ox.toRightXor(MissingX()).flatMap(x => if(x > 0)().right else NegativeX(x).left) 

Вы можете использовать mouse, который предоставляет аналогичные синтаксические хелперы для кошек:

import com.github.benhutchison.mouse.boolean._ 

ox.toRightXor(MissingX()).flatMap(x => (x > 0).toXor(NegativeX(x),())) 

Xor также метод ensure сделать что-то вроде этого, но это не дает вам доступ к элементу если предикат не выполняется. Если вы не нуждаетесь в x для NegativeX, вы могли бы написать:

ox.toRightXOr(MissingX()).ensure(Negative())(_ > 0).void 
+0

Спасибо, версия 'scalaz' выглядит лучше, хотя ... – Michael