Scala: Something like Option (Some, None) but with three states: Some, None, Unknown

让人想犯罪 __ 提交于 2019-12-05 07:38:32

Here's a barebones implementation. You probably want to look at the source for the Option class for some of the bells and whistles:

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]

Don't tell anyone I suggested this, but you could always use null for Unknown rather than writing a new class.

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

You can grab some stuff from Lift: the Box. It has three states, Full, Failure and Empty. Also, Empty and Failure both inherit from EmptyBox.

You can use scala.Either. Use Left for the exceptional value, and Right for the expected value which can be an Option in this case:

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)

You could create your own with the three possibilities. Or as of one your car.radioType types you could have unknown, and then use guards on your case's to handle it. If you roll your own, you should include the Product trait as well. liftweb has the Box type, which is an option close that allows for full, empty and erorr to happen.

I did something like similar to classify 3 types of lines in given file, a given line maybe, for instance, Float for header line, Long for a line in the middle (row), or String for the trailer line. Also isHeader, isRow and isTrailer can be used to know which one is. Hopefully helps:

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)
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!