[英]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
。 在创建语法时,似乎忽略了这种情况。
概观
{ 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:
对于其他表达式
e
,ex
被输入,好像它是{ 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.type
或C#(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.