Забавное наблюдение о (рекурсивных) структурных типах в Scala

Мне нужен был рекурсивный структурный тип в каком-то фрагменте кода с использованием признаков и структурного типа в качестве ограничения параметра типа. Он работал нормально, но позже я узнал, что Scala не поддерживает рекурсивные структурные типы.

Так может кто-нибудь объяснить мне, почему это работает нормально:

scala> trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {}
defined trait Test

а это не:

scala> def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null
<console>:5: error: illegal cyclic reference involving type M
       def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null

person urso    schedule 04.09.2010    source источник


Ответы (2)


Думаю, это глюк в компиляторе. Следующий код демонстрирует то же поведение, что и ваш исходный код:

trait Test[M[A] <: { def map: M[A] } ] {}
def test[M[A] <: { def map: M[A] } ] = null

Это приводит к ошибке времени компиляции: «недопустимая циклическая ссылка».

И следующий код не работает (т.е. компилируется нормально):

type S[M] = { def map: M }

trait Test[M[A] <: S[M[A]] ] {}
def test[M[A] <: S[M[A]] ] = null

Единственное отличие состоит в том, что здесь применяется структурная типизация через псевдоним типа S.

person michid    schedule 16.11.2010
comment
на самом деле мне нравится решение, использующее псевдонимы типов, и то, что оно работает даже для определений функций. Но ваш первый пример ведет себя точно так же, как мой, говоря, что Test-trait компилируется нормально. Но если он работает с псевдонимами типов, он определенно должен работать и без них?!? - person urso; 18.11.2010
comment
Да, я думаю, здесь есть некоторая несогласованность: он должен либо работать с псевдонимами типов и без них, либо вообще не работать. Вот почему я считаю, что это глюк в компиляторе. - person michid; 18.11.2010
comment
У вас есть номер для отслеживания ошибок? - person soc; 23.11.2010

Первый фрагмент кода также вызывает ошибку в Scala 2.7.7final:

scala> trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {}
<console>:4: error: illegal cyclic reference involving type M
       trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {}
                                                    ^

Какую версию Scala вы используете?

person Dzmitry Lazerka    schedule 09.11.2010