Scala:像Option(Some,None)之类的东西,但有三种状态:Some,None,Unknown

时间:2009-11-15 16:47:10

标签: scala nullable option

我需要返回值,当有人要求输入值时,告诉他们三件事之一:

  1. 这是值
  2. 没有价值
  3. 我们没有关于此值的信息(未知)
  4. 案例2与案例3略有不同。例如:

    val radio = car.radioType
    
    1. 我们知道价值:返回收音机类型,说“先锋”
    2. 湾没有价值:return None
    3. ℃。我们缺少关于这辆车的数据,我们不知道它是否有收音机
    4. 我以为我可以扩展scala的None并创建一个Unknown,但这似乎不可能。

      建议?

      谢谢!

      更新

      理想情况下,我希望能够编写如下代码:

      car.radioType match { 
         case Unknown => 
         case None => 
         case Some(radioType : RadioType) => 
      }
      

6 个答案:

答案 0 :(得分:13)

这是一个准系统实现。您可能希望查看一些铃声和口哨的Option类的源代码:

package example

object App extends Application {
  val x: TriOption[String] = TriUnknown

  x match {
    case TriSome(s) => println("found: " + s)
    case TriNone => println("none")
    case TriUnknown => println("unknown")
  }
}

sealed abstract class TriOption[+A]
final case class TriSome[+A](x: A) extends TriOption[A]
final case object TriNone extends TriOption[Nothing]
final case object TriUnknown extends TriOption[Nothing]

答案 1 :(得分:8)

不要告诉任何我建议过的人,但你总是可以使用null代替Unknown而不是写一个新类。

car.radioType match { 
   case null => 
   case None => 
   case Some(radioType : RadioType) => 
}

答案 2 :(得分:5)

你可以从Lift:the Box中抓取一些东西。它有三种状态,Full,Failure和Empty。此外,Empty和Failure都从EmptyBox继承。

答案 3 :(得分:4)

你可以使用scala.Either。使用Left表示例外值,Right表示期望值,在这种情况下可以是Option:

scala> type Result = Either[String, Option[String]]
defined type alias Result

scala> val hasValue: Result = Right(Some("pioneer"))
hasValue: Result = Right(Some(pioneer))

scala> val noValue: Result = Right(None)
noValue: Result = Right(None)

scala> val unknownValue = Left("unknown")
unknownValue: Left[java.lang.String,Nothing] = Left(unknown)

答案 4 :(得分:2)

您可以使用三种可能性创建自己的。或者你的car.radioType类型可能是未知的,然后在你的案例中使用警卫来处理它。 如果你自己动手,你也应该包括产品特性。 liftweb有Box类型,这是一个选项close,允许完整,空和erorr发生。

答案 5 :(得分:0)

我做了类似的事情,在给定文件中对3种类型的行进行了分类,例如,对于标题行可以是Float,对于中间的行(行)可以是Long,或者String作为预告片。此外,isHeaderisRowisTrailer可用于了解哪一个。希望有所帮助:

sealed abstract class HRT[+H, +R, +T] {
  val isHeader: Boolean
  val isRow: Boolean
  val isTrailer: Boolean
}

final case class Header[+H, +R, +T](h: H) extends HRT[H, R, T] {
  override val isHeader: Boolean = true
  override val isRow: Boolean = false
  override val isTrailer: Boolean = false
}

final case class Row[+H, +R, +T](r: R) extends HRT[H, R, T] {
  override val isHeader: Boolean = false
  override val isRow: Boolean = true
  override val isTrailer: Boolean = false
}

final case class Trailer[+H, +R, +T](t: T) extends HRT[H, R, T] {
  override val isHeader: Boolean = false
  override val isRow: Boolean = false
  override val isTrailer: Boolean = true
}

object Demo {
  def getEntries(): Seq[HRT[Float, Long, String]] =
    List(
      Header(3.14f),
      Row(42),
      Trailer("good bye")
    )

  val entries = getEntries()

  entries.foreach {
    case Header(f) => printf("header: %f\n", f)
    case Row(l) => printf("row: %d\n", l)
    case Trailer(s) => printf("trailer: %s\n", s)
  }
}