- Learn Scala Programming
- Slava Schmidt
- 510字
- 2021-06-10 19:35:44
Literal types
Scala 2.13 introduced a special kind of singleton type—the literal type. It denotes a single value of some literal and represents the most precise type of this literal. It is available for all types for which literal syntax is available (for example, Boolean, Char, String, and Symbol). It is impossible to define a literal type for Unit (by specification) and for Byte and Short (because there is no syntax to define literals of such types). This is how it works in practice:
scala> def bool2String(b: true) = "ja"
bool2String: (b: true)String
scala> bool2String(true)
res7: String = ja
scala> bool2String(false)
^
error: type mismatch;
found : Boolean(false)
required: true
There are two ways to define a variable of a literal type. The first way is by using an explicit type ascription, and the second way is by making it a non-lazy final:
scala> val a1: true = true
a1: true = true
scala> bool2String(a1)
res10: String = ja
scala> final val a2 = true
a2: Boolean(true) = true
scala> bool2String(a2)
res11: String = ja
scala> // but
scala> val a3 = true
a3: Boolean = true
scala> bool2String(a3)
^
error: type mismatch;
found : a3.type (with underlying type Boolean)
required: true
A literal type is erased to the normal type during compilation, and so it is not possible to override methods using literal types:
scala> object scope {
| def bool2String(b: true) = "ja"
| def bool2String(b: false) = "nein"
| }
def bool2String(b: false) = "nein"
^
On line 3: error: double definition:
def bool2String(b: true): String at line 2 and
def bool2String(b: false): String at line 3
have same type after erasure: (b: Boolean)String
In the previous snippet, the compiler prevented us from declaring two methods with the same name, and so took a parameter with a different literal type because of the erasure.
The singleton type forming the .type operator can be used to specify that a function should return a literal type and not a normal type, as demonstrated by the type of t inferred by the compiler—42:
scala> def singleOut[T](t: T): t.type = t
singleOut: [T](t: T)t.type
scala> final val t = singleOut(42)
t: 42 = 42
Since Scala 2.13, there is a type class called scala.ValueOf[T] and an operator called scala.Predef.valueOf[T] that can be used to yield values for singleton types. This is how valueOf[T] is defined:
def valueOf[T](implicit vt: ValueOf[T]): T = vt.value
And this is how it can be used:
scala> final val a = valueOf[42]
a: 42 = 42
The pattern matching against literal types also works as expected, though the syntax is unusual and probably not very useful, as demonstrated by this first case:
scala> def int2str(i: Int) = i match {
| case t: 42 => "forty-two"
| case ii => ii.toString
| }
int2str: (i: Int)String
scala> int2str(42)
res24: String = forhty-two
scala> int2str(43)
res25: String = 43
These literal types are probably not very interesting for day-to-day programming, but are very useful for type-level library development.
- Python快樂編程:人工智能深度學(xué)習(xí)基礎(chǔ)
- Magento 2 Theme Design(Second Edition)
- Java編程指南:基礎(chǔ)知識(shí)、類庫應(yīng)用及案例設(shè)計(jì)
- C#程序設(shè)計(jì)(慕課版)
- 基于免疫進(jìn)化的算法及應(yīng)用研究
- TypeScript圖形渲染實(shí)戰(zhàn):基于WebGL的3D架構(gòu)與實(shí)現(xiàn)
- Java程序設(shè)計(jì)與實(shí)踐教程(第2版)
- C和C++游戲趣味編程
- Windows Embedded CE 6.0程序設(shè)計(jì)實(shí)戰(zhàn)
- GameMaker Essentials
- Julia 1.0 Programming Complete Reference Guide
- 精通MySQL 8(視頻教學(xué)版)
- Raspberry Pi Robotic Blueprints
- C指針原理揭秘:基于底層實(shí)現(xiàn)機(jī)制
- Tableau Desktop可視化高級(jí)應(yīng)用