Введите Lambda в Scala: зачем нужны дополнительные скобки в декларации?

Введение:

В соответствии с моим пониманием объявление типа {type λ[α] = Either[A, α]} обозначает любой тип, у которого есть другой тип λ[α] как его член (в том же смысле, что и методы, являются членами класса). Это структурный тип, а именно его структура состоит в том, что он имеет объявление псевдонима типа λ[α] в качестве его члена.

С другой стороны, ({type λ[α] = Either[A, α]})#λ относится к только λ из-за проекции типа через #.

Вопрос:

Почему круглые скобки нужны для {type λ[α] = Either[A, α]} при выполнении проекции типа? Почему не просто {type λ [α] = Либо [A, α]} # λ?

Другими словами, то, что является точным деревом синтаксического анализа для ({type λ[α] = Either[A, α]})#λ в соответствии с грамматикой описания Scala (см. ниже )?

Почему {type λ[α] = Either[A, α]}#λ не правильное "предложение" в этой грамматике?

  Type              ::=  FunctionArgTypes ‘=>’ Type
                      |  InfixType [ExistentialClause]
  FunctionArgTypes  ::=  InfixType
                      |  ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
  ExistentialClause ::=  ‘forSome’ ‘{’ ExistentialDcl
                             {semi ExistentialDcl} ‘}’
  ExistentialDcl    ::=  ‘type’ TypeDcl
                      |  ‘val’ ValDcl
  InfixType         ::=  CompoundType {id [nl] CompoundType}
  CompoundType      ::=  AnnotType {‘with’ AnnotType} [Refinement]
                      |  Refinement
  AnnotType         ::=  SimpleType {Annotation}
  SimpleType        ::=  SimpleType TypeArgs
                      |  SimpleType ‘#’ id
                      |  StableId
                      |  Path ‘.’ ‘type’
                      |  ‘(’ Types ‘)’
  TypeArgs          ::=  ‘[’ Types ‘]’
  Types             ::=  Type {‘,’ Type}

Ответ 1

Вам также необходимо рассмотреть

CompoundType    ::=  AnnotType {‘with’ AnnotType} [Refinement]
                  |  Refinement
Refinement      ::=  [nl] ‘{’ RefineStat {semi RefineStat} ‘}’
RefineStat      ::=  Dcl
                  |  ‘type’ TypeDef
                  |

неофициальное описание

# может следовать только за SimpleType, но {type λ[α] = Either[A, α]} является Refinement, что в конечном итоге является Type.

Единственный способ получить SimpleType из общего Type - окружить его скобками.

формальный вывод

SimpleType
'(' Types ')' '#' id
'(' Type ')' # id
'(' InfixType ')' # id
'(' CompoundType ')' # id
'(' Refinement ')' # id
'(' '{' RefineStat '}' ')' # id
'(' '{' 'type' TypeDef '}' ')' # id
         ...
({ type λ[α] = Either[A, α] })#λ

Ответ 2

# требуется SimpleType:

SimpleType ‘#’ id

Однако { … } является Refinement (см. CompoundType), который не является SimpleType, если не заключен в скобки (см. ‘(’ Types ‘)’).

Итак, дерево разбора ({type λ[α] = Either[A, α]})#λ выглядит следующим образом:

      SimpleType ‘#’ id
          /           \
   ‘(’ Types ‘)’      'λ'
         |
        Type
         =
      InfixType
         =
    CompoundType
         =
     Refinement