持续What is "prolog style" in Scala?
我想结合逻辑推理和过程代码,在Scala-3中。就像这样:
// This is a mix of Prolog and Scala, and is not a real code.
// The idea is not only to find out that the goal is reachable,
// but to use the found solution
print_file(X:Filename) :- read(X,Representation), print(Representation).
read(X:Filename, CollectionOfLines[X]) :- { read_lines(X) }.
read(X:Filename, String[X]) :- { slurp_file(X) }.
print(X:String) :- { print(X) }.
print(X:CollectionOfLines) :- { X.foreach(println)}.
given Filename("foo.txt")
val howto = summon[print_file]
howto()我希望这样的程序能打印指定的文件。但到目前为止,我还不知道如何在Scala中指定过程部分。
发布于 2022-09-06 19:38:27
(这篇文章所包含的代码旨在演示类型系统的一些属性;它没有直接的实际应用程序,请不要将它用于任何事情;“它可以做”并不意味着“您应该这么做”)
在您的问题中,还不完全清楚"CollectionOfLines[X]“和"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时,它将打印自己的代码两次,一次作为一个长的多行字符串,一次作为编号行的列表。
正如在其他地方已经提到的那样,这个特定的用例看起来非常不典型,而且代码看起来非常统一。
您应该尝试保留这种机制,用于生成有关类型和类型构造函数的真实和精确的语句,而不是强制执行一组命令式语句之间的顺序。
在这个例子中,我们没有仔细地做出普遍正确的陈述,而是做了一堆半生不熟的、没有经过深思熟虑的陈述,给它们取了半随机的名字,然后试图滥用标称式系统,并将现实强加于人为的约束,我们把这些或那样的东西命名出来。这通常是一个糟糕的设计的标志:所有的东西都感觉很松散--“松弛”。特别是apply(): Unit显然是一个危险的标志:没有多少关于Unit的东西也可以被编码为类型,所以我们不需要依赖类型系统,而必须恢复到“严格类型的”命名纪律,然后希望人们已经正确地解释了名称。
https://stackoverflow.com/questions/73625638
复制相似问题