Me gustaría saber cómo funcionan los tipos del miembro en Scala, y cómo debo asociar tipos.Mecanografíe los parámetros contra tipos del miembro en Scala
Un enfoque es hacer que el tipo asociado sea un parámetro de tipo. Las ventajas de este enfoque es que puedo prescribir la varianza del tipo, y puedo estar seguro de que un subtipo no cambia el tipo. Las desventajas son que no puedo inferir el parámetro de tipo del tipo en una función.
El segundo enfoque es hacer que el tipo asociado sea un miembro del segundo tipo, que tiene el problema de que no puedo prescribir límites en los tipos asociados de los subtipos y, por lo tanto, no puedo usar el tipo en los parámetros de función (cuando x: X, X # T podría no estar en cualquier relación con xT)
un ejemplo concreto sería:
tengo un rasgo para DFAs (podría ser sin el parámetro de tipo)
trait DFA[S] { /* S is the type of the symbols in the alphabet */
trait State { def next(x : S); }
/* final type Sigma = S */
}
y quiero crear una función para ejecutar este DFA a través de una secuencia de entrada, y quiero
- la función debe tomar nada
<% Seq[alphabet-type-of-the-dfa]
tipo secuencia de entrada - función de la persona que llama no es necesario especificar los parámetros de tipo, todo debe inferirse
- que había como la función a llamar con el tipo de DFA concreto (pero si hay una solución donde la función no tendría un parámetro de tipo para el DFA, está bien)
- los tipos de alfabeto no deben restringirse (es decir. tiene que haber un DFA para Char, así como para una clase definida por el usuario aún desconocido)
- la DFA con diferentes tipos alfabeto no son subtipos
He intentado esto:
def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = ....
funciona este , excepto que el tipo S no se infiere aquí, así que tengo que escribir la lista de parámetros de tipo completo en cada sitio de llamadas.
def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]](... same as above
esto no funcionaba (referencia circular no válido para escribir D ??? (¿qué es?))
También he eliminado el parámetro de tipo, creé un tipo abstracto Sigma y trató de unión de ese tipo en las clases concretas runDFA se vería
def runDFA[D <: DFA, SQ <% Seq[D#Sigma]](... same as above
pero esto corre inevitablemente en problemas como la "coincidencia de tipos: se espera dfa.Sigma
, consiguió D#Sigma
"
¿Alguna idea? ¿Punteros?
Editar:
Como las respuestas indican que no hay una forma sencilla de hacer esto, alguien podría elaborar más sobre por qué es imposible y lo que tendría que ser cambiado por lo que funcionó?
Las razones por las que quiero que runDFA sea una función gratuita (no un método) es que quiero otras funciones similares, como la minimización de autómatas, operaciones regulares de lenguaje, conversiones de NFA a DFA, factorización de lenguaje etc. y tener todas esto dentro de una clase es justo contra casi cualquier principio del diseño OO.
Guau, pensé que querías decir esto: http://www.huygens-fokker.org/scala/ – MusiGenesis