2014-09-24 76 views
0

我希望能够传递“无”的可选原因。我尝试了延长“无”恩:扩展选项w /原因

case class NoneReason(reason: String) extends None 

却得到了一个“未发现:类型无”,然后我想:

case class NoneReason(reason: String) extends Option[Nothing] { 
    def isEmpty = true 
    def get = throw new NoSuchElementException("None.get") 
} 

,但我从密封类选一“”非法继承“

我猜这是一个特殊的情况,因为‘无’实际上是空或东西的别名。

我认为复制选项源,并将其重命名为TriOption或东西,但日似乎很难维持。什么将是一个优雅的方式来解决这个问题?

+5

您可以使用'Try [T]'或'Either [String,T]'而不是创建自己的类型。 – Lee 2014-09-24 21:17:32

+0

没有特殊情况,'None'不是任何别名,尤其不是'null'的别名。所有'Option'类都是密封的,最终的或者case对象,这些都是你的意图,你不应该能够扩展这些,你不能。一个简单的例子是'Option(something)match {case Some(x)=> ... case None => ...}'编译器可以检查您是否匹配了所有可能的情况,因为'Option'不是可扩展到基础包之外。正如@Lee所建议的,你应该使用不同的数据结构,比如'Either [String,T',它基本上是你的'NonReason'类型。 – Noah 2014-09-24 21:23:53

+0

子类型不是惯用的FP;此外,它使代码更复杂,并禁用了例如匹配情况静态耗尽检查。 – 2014-09-25 12:17:42

回答

4

None的一个可选原因是Either[Option[String], Foo],其中Foo是您的类型。您不能延伸None;这是一个单身人士,所以你可以认为它是一个值,如null

但是Either类用于在两个选择之间进行选择,按照惯例包含“正确”答案的正确分支(如果一个比另一个更正确)。如果你想要一个可选的错误信息,那就在左边的分支中。因此,您可以切换到上面显示的类型,然后切换到任何您通常使用的位置Option,您可以将x.right.toOption转换为不带消息的选项,或使用模式匹配或其他任何方式,例如

x match { 
    case Right(foo) => useFoo(foo) 
    case Left(None) => throw new Exception("Something went wrong.") 
    case Left(Some(msg)) => throw new Exception(msg + " went wrong.") 
} 

如果你觉得这有太多的样板,你可以使用ScalaUtilsScalaz或任何一个数字,有一个选项与 - 原因替代其他库的。 ScalaUtils非常容易上手。斯卡拉斯要深得多,如果你需要的深度真棒,并且如果你不意味着开始提高生产力需要更长的时间。

+0

对于ScalaUtils Or&Every而言+1 – Jean 2014-09-25 07:32:47

0

无不是空的别名。它是一个扩展了Option [Nothing]的对象(单例)。
您无法扩展它的原因是Option是密封类,这意味着它只能通过与密封类相同的文件中的类进行扩展。
正如Lee在您的问题的评论中所写的那样,要走的路是使用Try[T]Either[String, T]
Here一些很好的解释如何使用它们。