Reputation: 13892
I need to return values, and when someone asks for a value, tell them one of three things:
case 2 is subtly different than case 3. Example:
val radio = car.radioType
I thought I might extend scala's None and create an Unknown, but that doesn't seem possible.
suggestions?
thanks!
Update:
Ideally I'd like to be able to write code like this:
car.radioType match {
case Unknown =>
case None =>
case Some(radioType : RadioType) =>
}
Upvotes: 6
Views: 4139
Reputation: 982
With Scala 3 you can use union types like this:
object Unknown
object Empty
type MaybeRadio = RadioType | Empty.type | Unknown.type
car.radioType match
case Unknown => ???
case Empty => ???
case radioType: RadioType => ???
See https://docs.scala-lang.org/scala3/book/types-union.html
Upvotes: 0
Reputation: 783
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)
}
}
Upvotes: 0
Reputation: 12158
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) =>
}
Upvotes: 10
Reputation: 297185
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.
Upvotes: 5
Reputation: 13196
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]
Upvotes: 13
Reputation: 11596
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)
Upvotes: 4
Reputation: 3634
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.
Upvotes: 2