2010-09-04 3 views
24

Avevo bisogno di un tipo strutturale ricorsivo in qualche parte di codice usando i tratti e il tipo strutturale come vincolo del parametro di tipo. Ha funzionato bene, ma in seguito ho imparato che Scala non supporta i tipi strutturali ricorsivi.Divertente osservazione sui tipi strutturali (ricorsivi) in Scala

Così Qualcuno mi può spiegare perché questo funziona bene:

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

e questo non:

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 

risposta

6

Penso che questo sia un problema tecnico nel compilatore. Il seguente codice presenta lo stesso comportamento come codice iniziale:

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

Essa si traduce in un errore di compilazione: 'riferimento ciclico illegale'.

E il seguente codice non lo fa (cioè esso compila bene):

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

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

L'unica differenza è che digitando strutturale viene applicato attraverso un tipo alias S qui.

+0

in realtà mi piace la soluzione utilizzando alias di tipo e che funziona anche per le definizioni di funzione. Ma il tuo primo esempio si comporta esattamente come il mio, dicendo che il Test-tratto si compila bene. Ma se funziona usando i pseudonimi, sicuramente dovrebbe funzionare anche senza usarli?!? – urso

+0

Sì, penso che ci sia qualche incongruenza qui: dovrebbe funzionare con alias di tipo e senza o non dovrebbe funzionare affatto. Ecco perché penso che questo sia un problema tecnico nel compilatore. – michid

+0

Hai un numero di inseguitore di bug? – soc

0

Il primo frammento di codice tiri anche di errore nella 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] } ] {} 
                ^

Quale versione di Scala usi?

+0

WOrks in Scala 2.8.1 – tstenner

+0

Sto usando scala 2.8.0 – urso