Scala: что-то вроде Option (Some, None), но с тремя состояниями: Some, None, Unknown

мне нужно вернуть значения, и когда кто-то просит значение, скажите им одну из трех вещей:

  1. здесь значение
  2. не имеет значения
  3. у нас нет информации об этом значении (неизвестно)

случай 2 тонко отличается от случая 3. Пример:

val radio = car.radioType
  1. мы знаем значение: возвратите тип радио, скажите "Пионер"
  2. b. нет значения: return None
  3. Си. нам не хватает данные об этом автомобиле, мы не знаем, есть ли у него радио или нет

Я думал, что могу расширить Scala None и создать неизвестное, но это кажется невозможным.

предложения?

спасибо!

обновление:

в идеале я хотел бы написать примерно такой код:

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

6 ответов


вот реализация barebones. Вероятно, вы хотите посмотреть источник для класса 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]

никому не говорите, что я предложил это, но вы всегда можете использовать null для неизвестного, а не писать новый класс.

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

вы можете захватить некоторые вещи из лифта: коробка. Она имеет три состояния: полное, несостоятельное и пустое. Кроме того, Empty и Failure наследуются от EmptyBox.


вы можете использовать scala.Любой. Используйте Left для исключительного значения и Right для ожидаемого значения, которое может быть опцией в этом случае:

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)

вы можете создать свой собственный с трех возможностей. Или как одна из ваших машин.типы радиотипов, которые вы могли бы неизвестны, а затем использовать охранников в вашем случае, чтобы справиться с этим. Если вы катите свой собственный, вы также должны включить характеристику продукта. liftweb имеет тип коробки, который является опцией закрыть, что позволяет полный, пустой и erorr произойти.


Я сделал что-то похожее на классификацию 3 типов строк в данном файле, возможно, заданная строка, например,Float в строке заголовка Long для строки в середине (строка) или String для линии прицепа. Также isHeader, isRow и isTrailer можно использовать, чтобы узнать, какой из них. Надеюсь поможет:

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)
  }
}