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.
Un constructor de tipos es un tipo que puede aplicar a argumentos de tipo para "construir" un tipo.
Un constructor de valores es un valor que puede aplicar a argumentos de valor para "construir" un valor.
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:
Un constructor de tipos es un tipo que puede aplicar a los argumentos de tipo adecuados para "construir" un tipo adecuado.
Un constructor de valores es un valor que puede aplicar a argumentos de valor adecuados para "construir" un valor adecuado.
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 tipo String
, 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:
Un constructor de tipos es un tipo que puede aplicar a argumentos de tipo (tipos propios o constructores de tipos) para "construir" un tipo adecuado (constructor).
Un constructor de valores es un valor que puede aplicar a argumentos de valores (valores propios o constructores de valores) para "construir" un valor adecuado (constructor).
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:
proper first-order higher-order
values 10 (x: Int) => x (f: (Int => Int)) => f(10)
types (classes) String List Functor
types String ({type λ[x] = x})#λ ({type λ[F[x]] = F[String]})#λ
Donde las clases utilizadas se definieron como:
class String
class List[T]
class Functor[F[_]]
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:
types (informally) String [x] => x [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be
(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}
)