Scala 是否具有用于投影嵌套单例类型的语法? [英] Does Scala have syntax for projection of a nested singleton type?

查看:38
本文介绍了Scala 是否具有用于投影嵌套单例类型的语法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class C {
  object O
}

val x: C#O.type = (new C).O // error: ';' expected but '.' found
val y: C#(O.type) = (new C).O // error: identifier expected but '(' found

这种类型有合法的语法吗?

Is there a legal syntax for this type?

val x: c.O.type forSome { val c: C } = (new C).O

给予

ScalaFiddle.scala:4: error: type mismatch;
 found   : ScalaFiddle.this.C#O.type
 required: c.type#O.type forSome { type c.type <: ScalaFiddle.this.C with scala.this.Singleton{} }
  val x: c.O.type forSome { val c: C } = (new C).O
                                                 ^

所以 Scala 编译器理解这种类型并将其显示为 C#O.type.似乎在创建语法时忽略了这种情况.

So Scala compiler understands this type and shows it as C#O.type. It seems this case was just overlooked when creating the grammar.

推荐答案

概览

  1. 尝试写下类型
  2. 一个 bash 脚本,其中列出了每次尝试以及一些清理过的错误消息
  3. 编辑 2018-04-11:不应该将 rhs 输入为 { val y = new C;y.O }?

<小时>

我无法证明它不可能,但至少我想确保我没有尝试就放弃.这不是真正的答案,而是失败尝试的列表,也许有人觉得很有趣,也许有人发现脚本(在第二部分)用于生成对报告他们的发现有用的错误消息列表......


I can't prove that it is impossible, but at least I wanted to make sure that I didn't give up without trying. It's not really an answer, rather a list of failed attempts, maybe someone finds it amusing, maybe someone finds the script (in the second part) for generating the list of error messages useful for reporting their findings...

尝试写下类型

对看起来最有希望的阿列克谢罗曼诺夫的尝试进行系统改写:

Systematic rewriting of AlexeyRomanov's attempt that looked most promising:

val o: x.O.type forSome { val x: C } = (new C).O
val o: x.type#O.type forSome { val x : C } = (new C).O
val o: t#O.type forSome { type t <: C with Singleton } = (new C).O

一些或多或少不系统地尝试使用类型 lambda 之类的构造:

Some more or less unsystematic attempts with type-lambda like constructs:

// boring, does nothing, identity, just to recall lambda-syntax
val o: ({ type R <: c.O.type forSome { val c: C } })#R = (new C).O
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[c.type forSome{val c: C}] = (new C).O
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[A forSome {type A <: C}] = (new C).O

嵌套forSome的实验:

val o: x.type forSome { val x: c.O.type forSome { val c: C }} =  (new C).O

C 中使用其他类型成员的实验:

Experiments with additional type members in C:

class C {
  object O
  type T = O.type
}

val o: C#T = (new C).O

这实际上编译,但修改了右手边,所以我猜它不算数:

This actually compiles, but modifies the right hand side, so I guess it doesn't count:

val o: c.O.type forSome { val c: C } = { val c = new C; c.O }

结论:在我看来不可能.

生成所有错误消息的 Bash 脚本

要生成所有错误消息(没有文件路径和功能警告),将此行上方的帖子部分保存为saved_post.txt,然后在同一目录下运行以下脚本:

To generate all the error messages (without file paths and feature warnings), save the part of the post above this line as saved_post.txt, and then run the following script in the same directory:

免责声明:此脚本实际上会修改文件系统中的文件.在运行它之前,请确保您真的了解它的作用,并且真的想要运行它.特别是,它会破坏文件newCdotO.scala".

Disclaimer: this script actually modifies files in your file system. Please make sure that you really understand what it does, and really want to run it, before running it. In particular, it destroys the file 'newCdotO.scala'.

#!/bin/bash

tempFile=newCdotO.scala
inputFile=saved_post.txt
grep -oE "^ *val o:.*$" $inputFile | \
while read codeLine
do
  printf '=%.0s' {0..80}
  echo ""
  echo "" > $tempFile
  echo "import scala.language.existentials" >> $tempFile
  echo "import scala.language.higherKinds" >> $tempFile
  echo "class C { object O; type T = O.type }" >> $tempFile
  echo "$codeLine" | tee -a $tempFile
  printf -- '-%.0s' {0..80}
  echo ""
  scala $tempFile 2>&1 | sed 's|^.*error:|error:|g'
done |
awk '{print "    "$0}'

这会生成以下错误消息墙(嘿,我已经尝试清理它!):

This generates the following wall of error messages (Hey, I've tried to clean it up!):

=================================================================================
val o: x.O.type forSome { val x: C } = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
 found   : this.C#O.type
 required: x.O.type forSome { val x: this.C }
val o: x.O.type forSome { val x: C } = (new C).O
                                               ^
one error found
=================================================================================
val o: x.type#O.type forSome { val x : C } = (new C).O
---------------------------------------------------------------------------------
error: ';' expected but '.' found.
val o: x.type#O.type forSome { val x : C } = (new C).O
               ^
one error found
=================================================================================
val o: t#O.type forSome { type t <: C with Singleton } = (new C).O
---------------------------------------------------------------------------------
error: ';' expected but '.' found.
val o: t#O.type forSome { type t <: C with Singleton } = (new C).O
          ^
one error found
=================================================================================
val o: ({ type R <: c.O.type forSome { val c: C } })#R = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
 found   : this.C#O.type
 required: AnyRef{type R <: c.type#O.type forSome { type c.type <: this.C }}#R
val o: ({ type R <: c.O.type forSome { val c: C } })#R = (new C).O
                                                                 ^
one error found
=================================================================================
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[c.type forSome{val c: C}] = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
 found   : this.C#O.type
 required: c.type(in type L)#O.type forSome { type c.type(in type L) <: c.type(in value o) forSome { type c.type(in value o) <: this.C with Singleton } with Singleton }
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[c.type forSome{val c: C}] = (new C).O
                                                                                                ^
one error found
=================================================================================
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[A forSome {type A <: C}] = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
 found   : this.C#O.type
 required: c.O.type forSome { val c: A forSome { type A <: this.C } }
val o: ({type L[A <: C] = c.O.type forSome { val c: A }})#L[A forSome {type A <: C}] = (new C).O
                                                                                               ^
one error found
=================================================================================
val o: x.type forSome { val x: c.O.type forSome { val c: C }} =  (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
 found   : this.C#O.type
 required: x.type forSome { val x: c.type#O.type forSome { type c.type <: this.C } }
val o: x.type forSome { val x: c.O.type forSome { val c: C }} =  (new C).O
                                                                         ^
one error found
=================================================================================
val o: C#T = (new C).O
---------------------------------------------------------------------------------
error: type mismatch;
 found   : this.C#O.type
 required: _1.O.type forSome { val _1: this.C }
val o: C#T = (new C).O
                     ^
one error found
=================================================================================
val o: c.O.type forSome { val c: C } = { val c = new C; c.O }
---------------------------------------------------------------------------------

编辑 2018-04-11:

刚刚在 6.4 中偶然发现了 这里规范:

Just stumbled upon this here in 6.4 of the specification:

对于其他表达式 ee.x 的类型就像 { val y = e;y.x },对于一些新名称 y.

For other expressions e, e.x is typed as if it was { val y = e; y.x }, for some fresh name y.

这句话之前描述not-other"表达式的部分似乎指的是普通名称和稳定标识符.鉴于规范中的这一条款,我并不完全清楚为什么 (new C).O 的类型与 {val y = new C; 不完全相同.y.O},因为这次重写后,有问题的代码

The parts before this sentence describing the "not-other" expressions seem to refer to ordinary names and stable identifiers. Given this clause in the specification, it is not entirely clear to me why (new C).O is not typed in exactly the same way as {val y = new C; y.O}, because after this rewriting, the problematic code

val o: c.O.type forSome { val c: C } = (new C).O

看起来就像我在上述一系列尝试中能提出的唯一可行的建议:

would look just like the only working proposal that I could come up with in the above series of attempts:

val o: c.O.type forSome { val c: C } = { val c = new C; c.O }

推断的类型 C#O.type 是否真的是一个错误,而 c.O.type forSome { val c: C } 是规范规定的类型?我不会说它一个错误,我对规范中使用的公式不够熟悉.

Could the inferred type C#O.type actually be a bug, and c.O.type forSome { val c: C } be the type mandated by the specification? I wouldn't go so far claiming that it is a bug, I'm not familiar enough with the formulations used in the spec.

这篇关于Scala 是否具有用于投影嵌套单例类型的语法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆