Bem, digitação fraca versus forte é vagamente definida. Além disso, como o mais próximo de um uso geral de 'tipagem forte' é referir coisas que dificultam a conversão de tipos, isso não deixa mais nada para descrever sistemas de tipos ainda mais fortes. É como dizer que se você pode carregar menos de 30 libras, você é fraco e todos que conseguem levantar mais estão na mesma categoria de 'forte' - uma distinção enganosa.
Então, eu prefiro a definição:
- Sistemas com tipos fracos usam tipos para impedir que você faça certas coisas (como erros)
- Sistemas fortemente tipificados usam tipos para fazer coisas por você
O que quero dizer com fazer coisas para você? Bem, vamos examinar a criação de uma API de conversão de imagem na estrutura Servant (em Haskell, mas você realmente não precisa saber disso para acompanhar, verá ...)
{-# LANGUAGE
TypeOperators,
DataKinds
#-}
import Codec.Picture
import Data.Proxy
import Network.Wai.Handler.Warp (run)
import Servant
import Servant.JuicyPixels
main :: IO ()
main = run 8001 conversion
Isso significa que queremos alguns módulos, incluindo o pacote Servant e o plug-in JuicyPixels para o Servant, e que o principal ponto de entrada do programa é executar a função 'conversion' na porta 8001 como servidor usando o back-end Warp. Ignore o bit do idioma.
conversion :: Application
conversion = serve (Proxy :: Proxy ConversionApi) handler
Isso significa que a função de conversão é um servidor em que a API deve corresponder ao tipo 'ConversionApi' e as solicitações são tratadas pela função handler
type ConversionApi
= ReqBody '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
:> Post '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
Isso está especificando o ConvesionApi
tipo. Ele diz que devemos aceitar os tipos de conteúdo recebidos especificados pela lista '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] e manipulá-los como uma DynamicImage, e que devemos retornar uma DynamicImage convertida no mesmo intervalo de conteúdo tipos. Não se preocupe exatamente com o que:> significa, pense nisso como mágica feliz por enquanto.
Portanto, dada a minha definição preferida, um sistema de tipo fraco agora pode garantir coisas como:
- Você não retorna o tipo de conteúdo de saída errado
- Você não analisa a solicitação recebida como o tipo de conteúdo errado
- Se nosso servidor fosse mais complicado, impediria a criação de URIs malformados, mas na verdade não retornamos nenhuma página HTML para conter links (e o tipo garante que não podemos!)
- Um sistema de digitação fraco realmente ambicioso pode até verificar se estamos lidando exaustivamente com todos os tipos de conteúdo recebidos e enviados, permitindo que o tipo também atue como um documento de especificação em vez de apenas uma restrição.
Todos os objetivos elevados, mas não o suficiente para se qualificar como um sistema fortemente tipado, dada a definição acima. E agora temos que chegar à parte mais difícil de escrever código que segue essa especificação. Em um sistema de tipos realmente forte , escrevemos:
handler = return
E então terminamos. É isso aí , não há mais código para escrever . Este é um servidor da web totalmente operacional (módulo que ocorreu algum erro de digitação). O tipo disse ao compilador tudo o que é necessário para criar nosso servidor Web a partir dos tipos e pacotes (módulos tecnicamente) que definimos e importamos.
Então, como você aprende a fazer isso na maior escala de aplicativos? Bem, realmente não é muito diferente de usá-los em aplicativos de menor escala. Tipos absolutos não se importam com a quantidade de código gravado relacionado a eles.
A inspeção do tipo de tempo de execução é algo que você provavelmente desejará evitar, porque isso reduz uma enorme quantidade de benefícios e permite que os tipos tornem seu projeto mais complicado de trabalhar, em vez de simplificar as coisas.
Como tal, é principalmente uma questão de prática modelar coisas com tipos. As duas principais maneiras de modelar as coisas (ou construir as coisas em geral) são de baixo para cima e de cima para baixo. A parte superior para baixo começa com o nível mais alto de operações e, à medida que você constrói o modelo, você tem partes nas quais está adiando a modelagem para mais tarde. A modelagem de baixo para cima significa que você começa com as operações básicas, assim como inicia com as funções básicas, depois cria modelos cada vez maiores até capturar completamente a operação do projeto. De baixo para cima é mais concreto e provavelmente mais rápido de construir, mas de cima para baixo pode informar melhor seus modelos de nível inferior sobre como eles realmente precisam se comportar.
Os tipos são como os programas se relacionam com a matemática, literalmente, então não há realmente um limite superior sobre o quão complicado eles podem ficar, ou um ponto em que você pode 'terminar' aprendendo sobre eles. Praticamente todos os recursos fora dos cursos universitários de nível superior são todos dedicados à forma como os tipos funcionam em algum idioma específico. Portanto, você precisa decidir isso também.
Da melhor forma que posso oferecer, os tipos podem ser estratificados da seguinte forma:
- De forma muito fraca, coisas como JavaScript, onde [] + {} está definido
- Digitado fracamente como Python, onde você não pode fazer [] + {}, mas isso não é verificado até você tentar
- Digitação fraca como C ou Java, onde você não pode fazer [] + {}, mas isso é verificado no momento da compilação, no entanto, você não possui os recursos de tipo mais avançados
- Abrangendo a fronteira entre tipos fracos e fortemente tipados, como metaprogramação de modelos C ++ e código Haskell mais simples, em que os tipos aplicam apenas propriedades.
- Totalmente em fortemente tipado, como programas Haskell mais complicados, onde os tipos fazem coisas, como mostrado acima
- Os tipos muito fortemente digitados, como Agda ou Idris, em que tipos e valores interagem e podem se restringir. Isso é tão forte quanto os sistemas de tipos obtêm, e a programação neles é o mesmo que escrever provas matemáticas sobre o que seu programa faz. Nota: codificar no Agda não está literalmente escrevendo provas matemáticas, tipos são teorias matemáticas e funções com esses tipos são exemplos construtivos que provam essas teorias.
Geralmente, quanto mais abaixo você está nessa lista, mais os tipos podem fazer por você, mas, no fundo, você está subindo na estratosfera e o ar está ficando um pouco mais fino - o ecossistema de pacotes é muito menor e você ' você terá que escrever mais coisas contra ter encontrado uma biblioteca relevante. A barreira de entrada também aumenta à medida que você desce, pois você precisa realmente entender o sistema de tipos o suficiente para escrever programas em grande escala.