Sistemas de tipos: nominal vs. estrutural, explícito vs. implícito


24

Estou um pouco confuso sobre a diferença entre sistemas do tipo nominal e estrutural. Alguém pode explicar como eles diferem?

Pelo que entendi:

  • Nominal: a compatibilidade do tipo é baseada no nome do tipo.
  • Estrutural: a compatibilidade de tipos é baseada na estrutura de tipos, por exemplo, em C, se 2 variáveis ​​são tipos de estruturas com nomes diferentes, mas a mesma estrutura, então seus tipos são compatíveis.

Agora, sobre explícito e implícito: por que é diferente da digitação estática e dinâmica? Na digitação estática, os tipos serão explícitos, enquanto na digitação dinâmica, os tipos são implícitos. Estou certo?

Respostas:


29

Em um sistema digitado dinamicamente, os valores têm tipos em tempo de execução, mas variáveis ​​e funções não. Em um sistema estaticamente digitado, variáveis ​​e funções têm tipos conhecidos e verificados em tempo de compilação. Por exemplo, em Python xpode ser qualquer coisa ; em tempo de execução, se é 1um número e se é "foo", é uma string. Você só saberia qual tipo xestava em tempo de execução e poderia ser diferente cada vez que você executava o programa. Em uma linguagem como Java, você escreveria int xse xfosse um número e saberia em tempo de compilação que xsempre deve ser um int.

Os tipos "explícito" e "implícito" referem-se a sistemas de tipos estáticos . A característica definidora de um sistema estático é que os tipos são conhecidos em tempo de compilação, mas não necessariamente que precisam ser gravados. Em Java, os tipos são explícitos - você precisa escrevê-los. Portanto, em Java, um método pode ser algo como:

public int foo(String bar, Object baz) { ... }

Os tipos são conhecidos no tempo de compilação (estático) e gravados (explícitos). No entanto, também existem idiomas que não o obrigam a escrever o tipo. Eles podem inferir o tipo de uma função do seu corpo e como ela é usada. Um exemplo seria OCaml, onde você pode escrever algo como:

let foo x = x + 1

Desde que você usou +, o OCaml pode descobrir que xdeve ser um inttodo por si só. Portanto, o tipo de foo( foo : int -> int) é conhecido em tempo de compilação, assim como o exemplo de Java. É totalmente estático. No entanto, como o compilador pode descobrir quais são os tipos por conta própria, você não precisa escrevê-los: eles estão implícitos.

Em resumo: se um sistema de tipos é explícito ou implícito é uma propriedade de sistemas estáticos . É uma questão completamente diferente de saber se um sistema de tipos é dinâmico ou estático.

Freqüentemente, você tem sistemas de tipos que às vezes são explícitos e às vezes implícitos.

Por exemplo, acredito que o C # permite inferir tipos usando a varpalavra - chave. Portanto, em vez de escrever int x = 10, você pode escrever var x = 10e o compilador descobre que xdeve ser um int. C ++ faz algo semelhante com auto. Esses sistemas geralmente são explícitos, mas têm alguma inferência.

Por outro lado, existem sistemas geralmente implícitos, mas às vezes forçam você a escrever uma assinatura de tipo. Haskell é um ótimo exemplo. Na maioria das vezes, Haskell pode inferir os tipos para você. No entanto, às vezes você pode escrever um código ambíguo show . read, onde Haskell não consegue descobrir os tipos por conta própria. Nesse caso, você seria forçado a especificar explicitamente o tipo de um showou de um read. Além disso, alguns recursos mais avançados do sistema de tipos (como o polimorfismo rank-n) tornam a inferência indecidível - ou seja, não é garantido que ele seja interrompido. Isso significa que o código que usa esse recurso geralmente precisa de assinaturas de tipo explícitas.


2
Na verdade, existem alguns idiomas com o que você poderia chamar de digitação dinâmica explícita . Normalmente, esses idiomas permitem que você anote expressões com tipos e, em seguida, esses tipos serão verificados no tempo de execução em relação ao tipo de tempo de execução da expressão.
Jörg W Mittag 01/01

apenas uma precisão: os sistemas de tipos não são implícitos ou explícitos. Trata-se apenas de inferência de tipo, que é essencialmente uma maneira de gerar termos válidos em um sistema de tipos a partir de uma sintaxe diferente (às vezes não especificada).
Eduardo Pareja Tobes

Boa resposta, mas isso não trata da tipagem nominal versus estrutural. Uma edição seria ótima.
lunchmeat317

7
  • static vs dynamic descreve quando os tipos são verificados (mais ou menos no tempo de compilação ou no tempo de execução)

  • nominal versus estrutural descreve quando dois tipos são considerados iguais.

(E existem variações, a mais conhecida é a variante da tipagem estrutural, que considera apenas o que é usado em vez de todo o tipo conhecido como tipagem de pato).

As quatro combinações (nominal estática, estrutural estática, nominal dinâmica, estrutural dinâmica) são possíveis, e as linguagens geralmente não são puramente de uma classe, mas têm aspectos que são de outras.

Por exemplo, os sistemas de tipos de C ++ são estáticos, principalmente nominais, mas estruturais quando você considera modelos (e você pode considerar parte dos problemas relacionados aos conceitos em C ++ como um conflito entre aqueles que desejam passar da tipagem duck para uma forma completa de tipografia estrutural e aqueles que desejam ir para a digitação nominal). E o uso de classes e herança permite usar uma digitação dinâmica e nominal em alguns casos.

Linguagem que sistemas de tipo dinâmico geralmente usam tipagem estrutural, mas CLOS como aspectos nominais.


1

Estrutural: a compatibilidade de tipos é baseada na estrutura de tipos, por exemplo, em C, se 2 variáveis ​​são tipos de estruturas com nomes diferentes, mas a mesma estrutura, então seus tipos são compatíveis.

Geralmente não é esse o caso. Tipagem estrutural significa que Bé um subtipo de Ase pode satisfazer Aa interface. Isso geralmente significa ter membros com o mesmo nome; não apenas a mesma estrutura na memória.

Isso difere da digitação nominativa que requer que supertipos sejam especificados na declaração.


1

A melhor explicação que eu já vi da distinção entre (na verdade subsunção de) sistemas do tipo dinâmico e estático está nesta postagem de blog de Bob Harper:

Seu ponto principal pode ser resumido como:

  • linguagens dinâmicas são aquelas linguagens estáticas com apenas um tipo

1
Os links podem ficar ruins; você deve citar os trechos mais relevantes do artigo, para que sejam preservados para a posteridade, mesmo que o blog dê certo.
Doval

2
Certo. Eu acho que neste caso a sentença eu adicionei é suficiente :)
Eduardo Pareja Tobes
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.