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

时间:2018-04-06 07:29:11

标签: 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

此类型是否有合法语法?

编辑:

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

2 个答案:

答案 0 :(得分:3)

<强>概述

  1. 尝试记下类型
  2. 一个bash脚本,列出每个尝试以及一些有点清理的错误消息
  3. 编辑2018-04-11:不应该将rhs键入{ val y = new C; y.O }
  4. 我无法证明它不可能,但至少我想确保我没有尝试就不放弃。 这不是一个真正的答案,而是一个失败的尝试列表,也许是某人 发现它很有趣,也许有人找到了脚本(在第二部分中),用于生成有助于报告其发现的错误消息列表......

    尝试记下类型

    系统地重写阿列克谢罗曼诺夫看起来最有希望的尝试:

    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:

    偶然发现了this here in 6.4 of the specification

      

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

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

    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是否真的是一个错误,而c.O.type forSome { val c: C }是规范规定的类型?我不会到目前为止声称它一个错误,我对规范中使用的配方不够熟悉。

答案 1 :(得分:1)

对象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无效:(