首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala中的"Prolog样式“:与过程代码混合?

Scala中的"Prolog样式“:与过程代码混合?
EN

Stack Overflow用户
提问于 2022-09-06 17:12:42
回答 1查看 75关注 0票数 2

持续What is "prolog style" in Scala?

我想结合逻辑推理和过程代码,在Scala-3中。就像这样:

代码语言:javascript
复制
// 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中指定过程部分。

EN

回答 1

Stack Overflow用户

发布于 2022-09-06 19:38:27

(这篇文章所包含的代码旨在演示类型系统的一些属性;它没有直接的实际应用程序,请不要将它用于任何事情;“它可以做”并不意味着“您应该这么做”)

在您的问题中,还不完全清楚"CollectionOfLines[X]“和"String[X]”之类的公式是什么意思。我冒昧地把它扭曲成可实现的东西:

代码语言:javascript
复制
/**
 * 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的东西也可以被编码为类型,所以我们不需要依赖类型系统,而必须恢复到“严格类型的”命名纪律,然后希望人们已经正确地解释了名称。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73625638

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档