Optionmonad是一种很好的表达方式来处理Scala中的某些东西或者什么都没有.但是如果在"无"发生时需要记录消息呢?根据Scala API文档,
Either类型通常用作scala.Option的替代,其中Left表示失败(按惯例),Right表示类似于Some.
但是,我没有运气找到使用Either的最佳实践或涉及处理失败的Either的良好实际示例.最后,我为自己的项目提出了以下代码:
def logs: Array[String] = {
def props: Option[Map[String, Any]] = configAdmin.map{ ca =>
val config = ca.getConfiguration(PID, null)
config.properties getOrElse immutable.Map.empty
}
def checkType(any: Any): Option[Array[String]] = any match {
case a: Array[String] => Some(a)
case _ => None
}
def lookup: Either[(Symbol, String), Array[String]] =
for {val properties <- props.toRight('warning -> "ConfigurationAdmin service not bound").right
val logsParam <- properties.get("logs").toRight('debug -> "'logs' not defined in the configuration").right
val array <- checkType(logsParam).toRight('warning -> "unknown type of …Run Code Online (Sandbox Code Playgroud) 我正在关注Coursera的Scala课程.我也开始阅读Odersky的Scala书.
我经常听到的是,在函数式语言中抛出异常并不是一个好主意,因为它会破坏控制流,我们通常会返回一个带有失败或成功的Either.似乎Scala 2.10也将提供那个方向的Try.
但是在书和课程中,马丁奥德斯基似乎并没有(至少现在)说异常是坏的,而且他经常使用它们.我也注意到方法断言/要求......
最后我有点困惑,因为我想遵循最佳实践,但他们不清楚,语言似乎是双向的...
有人可以解释一下我应该在哪种情况下使用什么?
据我了解,Scala"for"语法与Haskell的monadic"do"语法非常相似.在Scala中,"for"语法通常用于Lists和Options.我想将它与Eithers 一起使用,但默认导入中不存在必要的方法.
for {
foo <- Right(1)
bar <- Left("nope")
} yield (foo + bar)
// expected result: Left("nope")
// instead I get "error: value flatMap is not a member..."
Run Code Online (Sandbox Code Playgroud)
这个功能是通过一些导入提供的吗?
有一个轻微的障碍:
for {
foo <- Right(1)
if foo > 3
} yield foo
// expected result: Left(???)
Run Code Online (Sandbox Code Playgroud)
对于列表,它将是List().因为Option,它会None.Scala标准库是否为此提供了解决方案?(或许scalaz?)怎么样?假设我想为Either提供我自己的"monad实例",我怎么能这样做?
在我的空闲时间,我正在学习Haskell,所以这是一个初学者的问题.
在我的阅读中,我遇到了一个例子,说明如何Either a成为一个实例Functor:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
Run Code Online (Sandbox Code Playgroud)
现在,我试图理解为什么实现在Right值构造函数的情况下映射,但是在不是的情况下Left?
这是我的理解:
首先让我重写上面的例子
instance Functor (Either a) where
fmap g (Right x) = Right (g x)
fmap g (Left x) = Left x
Run Code Online (Sandbox Code Playgroud)
现在:
我知道 fmap :: (c -> d) -> f c -> f d
如果我们替换f,Either a我们得到fmap :: (c -> d) -> Either …
我有一些代码,如下所示,我有一个Eithers列表,我想把它变成一个列表...特别是(在这种情况下),如果列表中有任何Lefts,那么我返回a列表的左侧,否则我返回权利列表的权利.
val maybe: List[Either[String, Int]] = getMaybe
val (strings, ints) = maybe.partition(_.isLeft)
strings.map(_.left.get) match {
case Nil => Right(ints.map(_.right.get))
case stringList => Left(stringList)
}
Run Code Online (Sandbox Code Playgroud)
打电话get总让我觉得我必须遗漏一些东西.
有没有比较惯用的方法呢?
我正在尝试验证无效方法的参数,但我找不到解决方案......
谁能告诉我该怎么办?
我正在尝试这样的事情:
def buildNormalCategory(user: User, parent: Category, name: String, description: String): Either[Error,Category] = {
val errors: Option[String] = for {
_ <- Option(user).toRight("User is mandatory for a normal category").right
_ <- Option(parent).toRight("Parent category is mandatory for a normal category").right
_ <- Option(name).toRight("Name is mandatory for a normal category").right
errors : Option[String] <- Option(description).toRight("Description is mandatory for a normal category").left.toOption
} yield errors
errors match {
case Some(errorString) => Left( Error(Error.FORBIDDEN,errorString) )
case None => Right( buildTrashCategory(user) )
}
}
Run Code Online (Sandbox Code Playgroud) 当我戴上我的C帽时,我认为也许惯用的Clojure只做简单的事情并检查返回值.
当我戴上我的Java帽子时(不情愿地,我必须添加),我想我自己,因为Clojure在JVM上运行,自然的方式必须是使用JVM异常.
当我戴上我的功能帽时,我认为必须有某种monadic构造或线程宏可以以可组合的方式处理错误.
那么在Clojure程序中处理错误的惯用方法是什么?
假设我需要在Scala中转换Option[Int]为Either[String, Int].我想这样做:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number")) {x => Right(x)}
Run Code Online (Sandbox Code Playgroud)
不幸的是上面的代码没有编译,我需要Either[String, Int]显式添加类型:
ox.fold(Left("No number"): Either[String, Int]) { x => Right(x) }
Run Code Online (Sandbox Code Playgroud)
是否可以在不添加类型的情况下转换Option为Either这种方式?
您如何建议转换Option为Either?
在"Scala中的函数式编程"一书的"无异常处理错误"一章中,作者给出了:
Option,如果我们不关心实际的异常Either如果我们关心实际的异常但scala.util.Try没有提到.从我的角度来看,我认为Try当我们关心实际的异常时,它是非常合适的,为什么没有提到呢?我错过了什么理由?
在我的应用程序的某个地方,我Either ParserError MyParseResult从Parsec 收到一个.在下游,这个结果可以使用其他库完成其他一些解析.在第二阶段的解析过程中,也可能会出现某种错误,我希望将其作为a传递Left String,但为此我需要将结果从Parsec转换为String.为了实现这一点,我需要一个允许我Left使用show函数映射a 的函数.
我想的映射函数看起来像这样:
mapLeft :: (a -> b) -> Either a c -> Either b c
mapLeft f (Left x) = Left $ f x
mapLeft _ x = x
Run Code Online (Sandbox Code Playgroud)
但我很惊讶没有发现任何与hackage db相匹配的东西.所以现在我怀疑我是否正在使用正确的方法解决我的问题.
为什么标准库中没有这样的功能?我的做法有什么问题?