我从一些人那里听说,在Scala中,我们倾向于(像其他函数式语言一样)不打破控制流...相反,按惯例,我们返回错误Either Left.
但是我们如何从这个例外中得到stracktrace呢?现在我在左边返回一个Error带有代码,消息和原因的简单案例类(Error也是).但如果我有错误,我无法获得堆栈跟踪.如果我的应用程序变得复杂,可能很难找到返回的代码块Error......根本原因是必不可少的.
那么我们在实践中做了什么?
我应该返回,而不是自定义Error,java类型Exception或Throwable我的Left?在不丢失堆栈跟踪和原因等重要信息的情况下,Scala异常处理的最佳实践是什么?
我知道我通常可以只进行模式匹配,但有时我会发现这些函数很有用:
isLeft = either (const True) (const False)
isRight = either (const False) (const True)
Run Code Online (Sandbox Code Playgroud)
标准库中有类似的东西吗?
我想知道是否有可能创建某种"方法调用链",所有方法都返回相同的[错误,结果].
我想要做的是:连续调用所有方法,当方法返回一个Left(错误)时,然后停止方法调用并返回在调用链中找到的第一个Left.
我尝试了一些东西,包括折叠,地图,投影......但我是Scala的新手并没有找到任何优雅的解决方案.
我试过这样的事情:
def createUserAndMandatoryCategories(user: User) : Either[Error,User] = {
User.create(user).right.map {
Logger.info("User created")
Category.create( Category.buildRootCategory(user) ).right.map {
Logger.info("Root category created")
Category.create( Category.buildInboxCategory(user) ).right.map {
Logger.info("Inbox category created")
Category.create( Category.buildPeopleCategory(user) ).right.map {
Logger.info("People category created")
Category.create( Category.buildTrashCategory(user) ).right.map {
Logger.info("Trash category created")
Logger.info("All categories successfully created created")
Right(user)
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但它不起作用.无论如何,我真的不喜欢它所需的缩进.此外我想将Error转换为描述问题的新String(我想我应该使用fold?)
我正在寻找像这样写的东西:
val result : Either[String,CallResult] = call1.something("error 1 description")
.call2.something("error 2 description")
.call3.something("error 3 description")
.call4.something("error 4 description")
Run Code Online (Sandbox Code Playgroud)
是不是可以用Scala做这样的事情?也许同时使用Either和Option?
一个限制也是如果第一次调用失败,则不应该进行其他调用.我不想要一个解决方案,我称之为一切,然后加入eithers.
谢谢!
我需要将Iterable [[Throwable,String]]减少为[Throwable,Iterable [String]].我不知道这个操作是否相当普遍,在Iterable特征上没有发现任何内容.所以我写了这个函数:
def reduce[A, B](xs: Iterable[Either[A, B]]): Either[A, Iterable[B]] =
xs.collectFirst {
case Left(x) => x
} match {
case Some(x) => Left(x)
case None => Right(xs.collect{case Right(y)=> y})
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助我找到一个更好的方法,如果这不是吗?
我花了一半时间试图弄清楚如何使用EitherT作为处理代码中错误的方法.
我已经定义了这样的变压器堆栈.
-- Stuff Monad
data StuffConfig = StuffConfig {
appId :: T.Text,
appSecret :: T.Text
}
data StuffState = StuffState {
stateToken :: Maybe Token,
stateTime :: POSIXTime
}
newtype Stuff a = Stuff {
runStuff :: (ReaderT StuffConfig (StateT StuffState (EitherT T.Text IO))) a
} deriving (Monad, Functor, Applicative,
MonadIO,
MonadReader StuffConfig,
MonadState StuffState
)
askStuff :: StuffConfig -> Stuff a -> IO (Either T.Text a)
askStuff config a = do
t <- getPOSIXTime
runEitherT (evalStateT (runReaderT (runStuff …Run Code Online (Sandbox Code Playgroud) 假设我有一些函数可以引发异常.我正在包装他们返回Either[Throwable, <function return type>].(假设我需要Either而不是Try).
def fooWrapper(arg1: FooArg1, arg2: FooArg2) =
try Right(foo(arg1, arg2)) catch { case NonFatal(e) => Left(e) }
def barWrapper(arg1: BarArg1, arg2: BarArg2, a3: BarArg3) =
try Right(bar(arg1, arg2, artg3)) catch { case NonFatal(e) => Left(e) }
...
Run Code Online (Sandbox Code Playgroud)
现在我想写一个通用的包装器来摆脱bolierpllate代码.你会建议什么?
这可能是一个非常基本的 Haskell 问题,但让我们假设以下函数签名
-- helper functions
getWeatherInfo :: Day -> IO (Either WeatherException WeatherInfo)
craftQuery :: WeatherInfo -> Either QueryException ModelQuery
makePrediction :: ModelQuery -> IO (Either ModelException ModelResult)
Run Code Online (Sandbox Code Playgroud)
将上述所有内容链接到一个predict day函数中的天真方法可能是:
predict :: Day -> IO (Maybe Prediction)
predict day = do
weather <- getWeatherInfo day
pure $ case weather of
Left ex -> do
log "could not get weather: " <> msg ex
Nothing
Right wi -> do
let query = craftQuery wi
case query of
Left …Run Code Online (Sandbox Code Playgroud) 什么是Either在Scala中使用的惯用方法?例如,当使用时,Option我可以使用orElse方法获取当前的下一个可选值None.但是如何以Either同样的方式合作?我没有找到类似orElse 链接Either的方法(我知道有这样的方法并不是一个好主意,因为我们失去了Left价值)
编辑:实际上我有一系列if-elseif-elseif-else表达式,每个表达式返回Right或Left.我想重构我的代码,使其变得"更具功能性".所以,我可以取代它firstOption orElse secondOption orElse...,如果它是Option,但如何在这里使用Either?
我有这样的理解:
for {
(value1: String, value2: String, value3: String) <- getConfigs(args)
// more stuff using those values
}
Run Code Online (Sandbox Code Playgroud)
getConfigs返回一个Either[Throwable, (Seq[String], String, String)],当我尝试编译时,我收到此错误:
value withFilter is not a member of Either[Throwable,(Seq[String], String, String)]
Run Code Online (Sandbox Code Playgroud)
如何Either在for comprehension中使用此方法(返回一个)?
我正在创建一个回合制游戏。我想定义一个数据类型,从许多可能的类型中编码一种类型。这是一个励志的例子:
我已经Turn使用 GADT定义了一个类型,所以每个值的类型都Turn a说明了它的值。
data Travel
data Attack
data Flee
data Quit
data Turn a where
Travel :: Location -> Turn Travel
Attack :: Int -> Turn Attack
Flee :: Turn Flee
Quit :: Turn Quit
Run Code Online (Sandbox Code Playgroud)
现在我可以写出这样的类型decideTravel :: GameState -> Turn Travel,非常有表现力而且很好。
当我想返回多种可能的转弯类型之一时,就会出现问题。我想编写类似于以下的函数:
-- OneOf taking two types
decideFightingTurn :: GameState -> OneOf (Turn Attack) (Turn Flee)
-- OneOf takes three types
decideTurn :: GameState -> OneOf (Turn Attack) (Turn Travel) (Turn Quit)
Run Code Online (Sandbox Code Playgroud)
此 …