Deixe-me compensar o começo de uma confusão confusa com alguma desambiguação. Eu gosto de usar a analogia com o nível de valor para explicar isso, pois as pessoas tendem a estar mais familiarizadas com ela.
Um construtor de tipo é um tipo que você pode aplicar aos argumentos de tipo para "construir" um tipo.
Um construtor de valor é um valor que você pode aplicar aos argumentos de valor para "construir" um valor.
Construtores de valor são geralmente chamados de "funções" ou "métodos". Também se diz que esses "construtores" são "polimórficos" (porque podem ser usados para construir "coisas" de "forma" variável) ou "abstrações" (uma vez que abstraem o que varia entre instanciações polimórficas diferentes).
No contexto de abstração / polimorfismo, primeira ordem se refere ao "uso único" da abstração: você abstrai um tipo uma vez, mas esse tipo em si não pode abstrair nada. Os genéricos Java 5 são de primeira ordem.
A interpretação de primeira ordem das caracterizações acima de abstrações é:
Um construtor de tipo é um tipo que você pode aplicar a argumentos de tipo adequados para "construir" um tipo adequado.
Um construtor de valor é um valor que você pode aplicar a argumentos de valor adequados para "construir" um valor adequado.
Para enfatizar, não há abstração envolvida (acho que você poderia chamar isso de "ordem zero", mas eu nunca vi isso usado em nenhum lugar), como o valor 1
ou o tipo String
, geralmente dizemos que algo é um valor ou tipo "adequado".
Um valor adequado é "imediatamente utilizável" no sentido de que não está aguardando argumentos (não é abstraído sobre eles). Pense neles como valores que você pode imprimir / inspecionar facilmente (serializar uma função é trapaça!).
Um tipo adequado é um tipo que classifica valores (incluindo construtores de valor); os construtores de tipo não classificam nenhum valor (eles primeiro precisam ser aplicados aos argumentos de tipo corretos para produzir um tipo adequado). Para instanciar um tipo, é necessário (mas não suficiente) que seja um tipo adequado. (Pode ser uma classe abstrata ou uma classe à qual você não tem acesso.)
"Ordem superior" é simplesmente um termo genérico que significa uso repetido de polimorfismo / abstração. Significa o mesmo para tipos e valores polimórficos. Concretamente, uma abstração de ordem superior abstrai sobre algo que abstrai sobre algo. Para tipos, o termo "tipo superior" é uma versão para fins especiais da "ordem superior" mais geral.
Assim, a versão superior de nossa caracterização se torna:
Um construtor de tipo é um tipo que você pode aplicar aos argumentos de tipo (tipos adequados ou construtores de tipo) para "construir" um tipo adequado (construtor).
Um construtor de valor é um valor que você pode aplicar a argumentos de valor (valores adequados ou construtores de valor) para "construir" um valor adequado (construtor).
Assim, "ordem superior" significa simplesmente que, quando você diz "abstraindo sobre X", realmente entende! O X
que é abstraído não perde seus próprios "direitos de abstração": pode abstrair tudo o que deseja. (A propósito, eu uso o verbo "abstract" aqui para significar: deixar de fora algo que não é essencial para a definição de um valor ou tipo, para que possa ser variado / fornecido pelo usuário da abstração como argumento .)
Aqui estão alguns exemplos (inspirados nas perguntas de Lutz por email) de valores e tipos adequados, de primeira e de mais alta ordem:
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]})#λ
Onde as classes usadas foram definidas como:
class String
class List[T]
class Functor[F[_]]
Para evitar a indireção através da definição de classes, é necessário expressar de alguma forma funções de tipo anônimo, que não são expressáveis diretamente no Scala, mas você pode usar tipos estruturais sem muita sobrecarga sintática (o #λ
estilo é devido a https://stackoverflow.com / users / 160378 / retronym afaik):
Em alguma versão futura hipotética do Scala que suporta funções do tipo anônimo, você pode encurtar a última linha dos exemplos para:
types (informally) String [x] => x [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be
(Em uma nota pessoal, lamento já ter falado sobre "tipos de classe superior", eles são apenas tipos afinal! Quando você absolutamente precisar desambiguar, sugiro dizer coisas como "parâmetro do construtor de tipo", "membro do construtor de tipo" , ou "alias do construtor de tipos", para enfatizar que você não está falando apenas de tipos adequados.)
ps: Para complicar ainda mais, "polimórfico" é ambíguo de uma maneira diferente, pois um tipo polimórfico às vezes significa um tipo quantificado universalmente, como Forall T, T => T
, que é um tipo adequado, pois classifica valores polimórficos (em Scala, esse valor pode ser escrito como o tipo estrutural {def apply[T](x: T): T = x}
)