Puede encontrar lo siguiente en la web:
¿Tipo más alto == constructor de tipo?
class AClass[T]{...} // For example, class List[T]
Algunos dicen que este es un tipo de tipo superior, ya que abstrae sobre tipos que cumplirían con la definición.
Los tipos de tipo superior son tipos que toman otros tipos y construyen un nuevo tipo.
Sin embargo, estos también se conocen como constructor de tipos . (Por ejemplo, en Programación en Scala ).
¿Tipo de tipo superior == constructor de tipo que toma el constructor de tipo como parámetro de tipo?
En el artículo Generics of a Higher Kind , puedes leer
... tipos que se resumen sobre tipos que se resumen sobre tipos ('tipos de tipo superior') ... "
lo que sugiere que
class XClass[M[T]]{...} // or trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
Es un tipo de tipo superior.
Entonces, con esto en mente, es difícil distinguir entre constructor de tipos , tipo de tipo más alto y constructor de tipos que toma los constructores de tipos como parámetro de tipo , por lo tanto, la pregunta anterior.
Respuestas:
Permítanme compensar el comienzo de algo de esta confusión lanzando algo de desambiguación. Me gusta usar la analogía con el nivel de valor para explicar esto, ya que las personas tienden a estar más familiarizadas con él.
Los constructores de valores generalmente se denominan "funciones" o "métodos". También se dice que estos "constructores" son "polimórficos" (porque pueden usarse para construir "cosas" de "formas" variables) o "abstracciones" (ya que abstraen sobre lo que varía entre las diferentes instancias polimórficas).
En el contexto de la abstracción / polimorfismo, el primer orden se refiere al "uso único" de la abstracción: abstrae sobre un tipo una vez, pero ese tipo en sí mismo no puede abstraer sobre nada. Los genéricos de Java 5 son de primer orden.
La interpretación de primer orden de las caracterizaciones anteriores de abstracciones son:
Para enfatizar que no hay abstracción involucrada (supongo que se podría llamar a esto "orden cero", pero no he visto esto usado en ningún lado), como el valor
1
o el tipoString
, generalmente decimos que algo es un valor o tipo "adecuado".Un valor apropiado es "inmediatamente utilizable" en el sentido de que no está esperando argumentos (no los abstrae). Piense en ellos como valores que puede imprimir / inspeccionar fácilmente (¡serializar una función es hacer trampa!).
Un tipo adecuado es un tipo que clasifica los valores (incluidos los constructores de valores), los constructores de tipos no clasifican ningún valor (primero deben aplicarse a los argumentos de tipo correctos para producir un tipo adecuado). Para crear una instancia de un tipo, es necesario (pero no suficiente) que sea un tipo adecuado. (Puede ser una clase abstracta o una clase a la que no tiene acceso).
"Orden superior" es simplemente un término genérico que significa el uso repetido de polimorfismo / abstracción. Significa lo mismo para los tipos y valores polimórficos. Concretamente, una abstracción de orden superior abstrae sobre algo que abstrae sobre algo. Para los tipos, el término "superior" es una versión de propósito especial del "orden superior" más general.
Por lo tanto, la versión de orden superior de nuestra caracterización se convierte en:
Por lo tanto, "orden superior" simplemente significa que cuando dices "abstraer sobre X", ¡lo dices en serio! Lo
X
que se abstrae no pierde sus propios "derechos de abstracción": puede abstraer todo lo que quiera. (Por cierto, utilizo el verbo "abstracto" aquí para significar: dejar de lado algo que no es esencial para la definición de un valor o tipo, de modo que pueda ser variado / proporcionado por el usuario de la abstracción como argumento .)Estos son algunos ejemplos (inspirados en las preguntas de Lutz por correo electrónico) de valores y tipos adecuados, de primer orden y de orden superior:
Donde las clases utilizadas se definieron como:
Para evitar la indirección a través de la definición de clases, debe expresar de alguna manera funciones de tipo anónimo, que no se pueden expresar directamente en Scala, pero puede usar tipos estructurales sin demasiada sobrecarga sintáctica (el
#λ
estilo se debe a https://stackoverflow.com / users / 160378 / retronym afaik):En alguna versión hipotética futura de Scala que admita funciones de tipo anónimo, puede acortar esa última línea de los ejemplos a:
(En una nota personal, lamento haber hablado alguna vez de "tipos de tipo superior", ¡son solo tipos después de todo! Cuando necesite absolutamente desambiguar, sugiero decir cosas como "parámetro de constructor de tipos", "miembro de constructor de tipos" , o "alias de constructor de tipos", para enfatizar que no se trata solo de los tipos adecuados).
ps: para complicar aún más las cosas, "polimórfico" es ambiguo de una manera diferente, ya que un tipo polimórfico a veces significa un tipo cuantificado universalmente, como
Forall T, T => T
, que es un tipo apropiado, ya que clasifica los valores polimórficos (en Scala, este valor puede ser escrito como el tipo estructural{def apply[T](x: T): T = x}
)fuente
(Esta respuesta es un intento de decorar la respuesta de Adriaan Moors con información gráfica e histórica).
Los tipos de tipo superior son parte de Scala desde 2.5.
Antes de eso, Scala, como Java hasta ahora, no permitía usar el constructor de tipos ("genéricos" en Java) como parámetro de tipo para un constructor de tipos. p.ej
No fue posible.
(Imagen derivada de genéricos de un tipo superior )
La consecuencia es que ese constructor de tipos (p
List
. Ej. ) Podría usarse como otros tipos en la posición del parámetro de tipo de los constructores de tipos y, por lo tanto, se convirtieron en tipos de primera clase desde Scala 2.5. (Similar a las funciones que son valores de primera clase en Scala).En el contexto de un sistema de tipos que admite tipos superiores, podemos distinguir los tipos adecuados , tipos similares
Int
oList[Int]
de tipos de primer orden comoList
y tipos de tipo superior comoFunctor
oMonad
(tipos que resumen sobre tipos que resumen sobre tipos).El sistema de tipos de Java en el otro lado no admite tipos y, por lo tanto, no tiene tipos de "tipo superior".
Por lo tanto, esto debe verse en el contexto del sistema de tipos de soporte.
En el caso de Scala, a menudo ves ejemplos de un constructor de tipos como
con el título "Tipos más amables", por ejemplo, en Scala para programadores genéricos, sección 4.3
Esto a veces es engañoso, porque muchos se refieren
Container
como un tipo de tipo superior y noIterable
, pero lo que es más preciso es,fuente
El tipo de tipos ordinarios como
Int
yChar
, cuyas instancias son valores, es*
. El tipo de constructores de tipo unario comoMaybe
es* -> *
; constructores de tipo binario comoEither
have kind ( curry ) kind* -> * -> *
, y así sucesivamente. Puede ver los tipos comoMaybe
yEither
como funciones de nivel de tipo: toman uno o más tipos y devuelven un tipo.Una función es de orden superior si tiene un orden mayor que 1, donde el orden es (informalmente) la profundidad de anidación, a la izquierda, de las flechas de función:
1 :: Int
chr :: Int -> Char
fix :: (a -> a) -> a
,map :: (a -> b) -> [a] -> [b]
((A -> B) -> C) -> D
(((A -> B) -> C) -> D) -> E
Entonces, para resumir , un tipo de tipo superior es solo una función de orden superior de nivel de tipo.
Int :: *
Maybe :: * -> *
Functor :: (* -> *) -> Constraint
—higher-kinded: convierte constructores de tipo unario en restricciones de tipo de clasefuente
Functor
produce un tipo apropiado (bueno, rasgo, pero la misma idea) aFunctor[F[_]]
partir de un constructor de tiposF
.(* => *) => (* => *)
puede expresar el convertidor de tipos en Scala? Si no, en cualquier otro idioma?* ⇒ * ⇒ *
curry es muy útil. ¡Gracias!(* ⇒ *) ⇒ (* ⇒ *)
También se puede deletrear(* ⇒ *) ⇒ * ⇒ *
. Se puede expresar en Scala comoFoo[F[_], T]
. Este es el tipo de tipo como (en Haskell)newtype Twice f a = Twice (f (f a))
(por ejemplo,Twice Maybe Int
≅Maybe (Maybe Int)
,Twice [] Char
≅[[Char]]
) o algo más interesante como la mónada libredata Free f a = Pure a | Free (f (Free f a))
.Yo diría: un tipo de tipo superior se resume sobre un constructor de tipos. Por ejemplo, considere
Aquí
Functor
hay un "tipo de tipo superior" (como se usa en el "Genéricos de un tipo superior" ). No es un tipo de constructor concreto ("de primer orden")List
(que abstrae solo sobre los tipos adecuados). Resume sobre todos los constructores de tipo unario ("primer orden") (como se indica conF[_]
).O para decirlo de otra manera: en Java, tenemos constructores de tipo claro (p. Ej.
List<T>
), pero no tenemos "tipos de tipo superior", porque no podemos abstraer sobre ellos (por ejemplo, no podemos escribir laFunctor
interfaz definida anteriormente - al menos no directamente ).El término "polimorfismo de orden superior (constructor de tipos)" se utiliza para describir sistemas que admiten "tipos de tipo superior".
fuente
List<T>
en Java sería un constructor de tipo unario, ya que tiene claramente el tipo* -> *
. Lo que falta en la respuesta de Jon es que debe ser capaz de abstraer sobre "todo" (y no solo sobre el segundo*
como en Java) para llamarlo un tipo de tipo superior.def succ(x: Int) = x+1
introduce el "constructor de valores" (vea mi otra respuesta para lo que quiero decir con esto)succ
(nadie se referiría a este valor como succ (x: Int)). Por analogía,Functor
es el tipo (de hecho, más amable) definido en su respuesta. Una vez más, no debe referirse a ella comoFunctor[F[_]]
(¿qué esF
lo que es?_
Que no están en su alcance por desgracia, el azúcar sintáctica para los existenciales enturbia las aguas aquí haciendo?!F[_]
Abreviatura deF[T forSome {type T}]
)Scala REPL proporciona un
:kind
comando quePor ejemplo,
El
:help
proporciona definiciones claras, así que creo que vale la pena publicarlo aquí en su totalidad (Scala 2.13.2)fuente