繁体   English   中英

Scala是否具有投影嵌套单例类型的语法?

[英]Does Scala have syntax for projection of a nested singleton type?

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

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

编辑:

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 在创建语法时,似乎忽略了这种情况。

概观

  1. 几次尝试写下这种类型
  2. 一个bash脚本,它列出了每个尝试以及一些有点清理的错误消息
  3. 编辑2018-04-11:不应该将rhs键入为{ val y = new C; yO } { val y = new C; yO }好吗?

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


几次尝试写下这种类型

系统地改写了AlexeyRomanov的看起来最有希望的尝试:

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类构造的一些或多或少的非系统尝试:

// 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使用其他类型成员的实验:

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

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

这实际上编译,但修改右侧,所以我想它不计算:

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

结论:对我来说不可能。


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

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

免责声明:此脚本实际上修改了文件系统中的文件。 在运行之前,请确保您真正了解它的功能,并且确实想要运行它。 特别是,它会破坏文件'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}'

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

=================================================================================
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中偶然发现了这一点

对于其他表达式eex被输入,好像它是{ val y = e; yx } { val y = e; yx } ,对于一些新鲜的名字y

描述“非其他”表达式的句子之前的部分似乎是指普通名称和稳定标识符。 鉴于规范中的这一条款,我并不完全清楚为什么(new C).O的输入方式与{val y = new C; yO}完全相同{val y = new C; yO} {val y = new C; yO} ,因为在这次重写之后,有问题的代码

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

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

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

推断类型C#O.type实际上是否是一个错误,并且cOtype forSome { val c: C }是规范规定的类型? 我不会到目前为止声称这一个错误,我对规范中使用的配方不够熟悉。

对象O仅存在C的实例,因此其类型也需要与C的实例绑定。 因此,你不能做C#O.typeC#(O.type) ,但你需要先得到一个C实例,例如:

scala> class C { object O }
defined class C

scala> val x = new C
x: C = C@59f95c5d

scala> val y: x.O.type = x.O
y: x.O.type = C$O$@5679c6c6

编辑:Alexey Romanov在下面评论说我的结论是不正确的,这可以通过下面的例子来证明:

scala> class B { class A {} }
defined class B

scala> val t = new B
t: B = B@63d4e2ba

scala> val u: B#A = new t.A
u: B#A = B$A@1cd072a9

所以我实际上不知道为什么B#A有效,但C#O.type不起作用:(

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM