(这篇文章包含的代码旨在演示类型系统的一些属性;它没有直接的实际应用,请不要将其用于任何用途;“它可以完成”并不意味着“你应该这样做”)
在你的问题中,并不完全清楚诸如“CollectionOfLines[X]
" and "String[X]
” 的意思是。我冒昧地将它扭曲成可实现的东西:
/**
* Claims that an `X` can be printed.
*/
trait Print[X]:
def apply(x: X): Unit
/**
* Claims that an instance of type `X` can
* be read from a file with a statically
* known `Name`.
*/
trait Read[Name <: String & Singleton, X]:
def apply(): X
/**
* Claims that an instance of type `Repr` can
* be read from a statically known file with a given `Name`,
* and then printed in `Repr`-specific way.
*/
trait PrintFile[Name, Repr]:
def apply(): Unit
given splitLines: Conversion[String, List[String]] with
def apply(s: String) = s.split("\n").toList
given printFile[Name <: String & Singleton, Repr]
(using n: ValueOf[Name], rd: Read[Name, Repr], prnt: Print[Repr])
: PrintFile[Name, Repr] with
def apply(): Unit =
val content = rd()
prnt(content)
given readThenConvert[Name <: String & Singleton, A, B]
(using name: ValueOf[Name], readA: Read[Name, A], conv: Conversion[A, B])
: Read[Name, B] with
def apply() = conv(readA())
inline given slurp[Name <: String & Singleton]
(using n: ValueOf[Name])
: Read[Name, String] with
def apply() = io.Source.fromFile(n.value).getLines.mkString("\n")
given printString: Print[String] with
def apply(s: String) = println(s)
given printList[X](using printOne: Print[X]): Print[List[X]] with
def apply(x: List[X]) = x.zipWithIndex.foreach((line, idx) => {
print(s"${"%3d".format(idx)}| ")
printOne(line)
})
@main def printItself(): Unit =
println("Print as monolithic string")
summon[PrintFile["example.scala", String]]()
println("=" * 80)
println("Print as separate lines")
summon[PrintFile["example.scala", List[String]]]()
当另存为example.scala
,它将打印自己的代码两次,一次作为一个长多行字符串,一次作为编号行列表。
正如其他地方已经提到的,这个特定的用例看起来非常不典型,而且代码看起来很不惯用。
你应该尝试保留这个机制true and precise有关类型和类型构造函数的语句,而不是用于在一堆命令性语句之间强制执行顺序。
在这个例子中,我们没有仔细地做出普遍正确的陈述,而是做出了一堆半生不熟、未经深思熟虑的陈述,给它们半随机的名称,然后试图滥用名义类型系统并强制现实我们通过给事物这样或那样命名而施加的人为限制。这通常是糟糕设计的标志:一切都感觉松散且有点“松弛”。这apply(): Unit
特别是明显是一个危险信号:没有什么可说的Unit
它也可以被编码为类型,因此我们必须恢复到“字符串类型”命名规则,而不是依赖于类型系统,然后希望人们能够正确解释这些名称。