Bueno, la escritura débil frente a la fuerte está bastante vagamente definida. Además, dado que lo más cercano a un uso general de 'tipeo fuerte' es referir cosas que dificultan la conversión de tipos, eso no deja nada más para describir sistemas de tipos aún más fuertes. Es como decir que si puedes cargar menos de 30 libras eres débil, y todos los que pueden levantar más están en la misma categoría de 'fuerte', una distinción engañosa.
Entonces prefiero la definición:
- Los sistemas con tipos débiles usan tipos para evitar que usted haga ciertas cosas (como errores)
- Los sistemas fuertemente tipados usan tipos para hacer cosas por usted
¿Qué quiero decir con hacer cosas por ti? Bueno, examinemos cómo escribir una API de conversión de imágenes en el marco Servant (en Haskell, pero realmente no necesita saberlo para seguir, 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
Esto significa que queremos algunos módulos, incluido el paquete Servant y el complemento JuicyPixels para Servant, y que el punto de entrada principal del programa es ejecutar la función de 'conversión' en el puerto 8001 como el servidor que utiliza el backend Warp. Ignora el bit del idioma.
conversion :: Application
conversion = serve (Proxy :: Proxy ConversionApi) handler
Esto significa que la función de conversión es un servidor donde la API debe coincidir con el tipo 'ConversionApi' y las funciones son manejadas por la función handler
type ConversionApi
= ReqBody '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
:> Post '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
Esto especifica el ConvesionApi
tipo. Dice que deberíamos aceptar los tipos de contenido entrante especificados por la lista '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE], y manejarlos como una imagen dinámica, y que deberíamos devolver una imagen dinámica convertida en el mismo rango de contenido tipos. No se preocupe exactamente por lo que:> significa, solo piense en ello como magia feliz por ahora.
Entonces, dada mi definición preferida, un sistema de tipo débil ahora puede garantizar cosas como:
- No devuelve el tipo de contenido saliente incorrecto
- No analiza la solicitud entrante como el tipo de contenido incorrecto
- Si nuestro servidor fuera más complicado, nos impediría crear URI con formato incorrecto, pero en realidad no devolveremos ninguna página HTML que contenga enlaces (¡y el tipo asegura que no podamos!)
- Un sistema de escritura débil realmente ambicioso podría incluso verificar para asegurarse de que estamos manejando exhaustivamente todos los tipos de contenido entrante y saliente, permitiendo que el tipo también actúe como un documento de especificación en lugar de solo una restricción.
Todos los objetivos elevados, pero en realidad no son suficientes para calificar como un sistema fuertemente tipado, dada la definición anterior. Y ahora tenemos que llegar a la parte difícil de escribir código que siga esta especificación. En un sistema de tipos realmente fuerte , escribimos:
handler = return
Y luego terminamos. Eso es todo, no hay más código para escribir . Este es un servidor web totalmente operativo (módulo de cualquier error tipográfico que me perdí). El tipo le ha dicho al compilador todo lo que necesita para crear nuestro servidor web a partir de los tipos y los paquetes (módulos técnicamente) que definimos e importamos.
Entonces, ¿cómo aprende a hacer esto en la escala de aplicación principal? Bueno, en realidad no es muy diferente de usarlos en aplicaciones de menor escala. A los tipos que son absolutos no les importa cuánto código se escriba en relación con ellos.
La inspección de tipo de tiempo de ejecución es algo que probablemente querrá evitar, ya que reduce una gran cantidad del beneficio y permite que los tipos hagan que su proyecto sea más complicado de trabajar, en lugar de hacer que los tipos simplifiquen las cosas.
Como tal, es principalmente una cuestión de práctica modelar cosas con tipos. Las dos formas principales de modelar cosas (o construir cosas en general) son de abajo hacia arriba y de arriba hacia abajo. De arriba hacia abajo comienza con el nivel más alto de operaciones, y a medida que construye el modelo, tiene partes en las que difiere el modelado hasta más tarde. El modelado de abajo hacia arriba significa que comienza con operaciones básicas, al igual que comienza con funciones básicas, luego construye modelos cada vez más grandes hasta que haya capturado completamente la operación del proyecto. De abajo hacia arriba es más concreto y probablemente más rápido de construir, pero de arriba hacia abajo puede informar mejor a sus modelos de nivel inferior sobre cómo deben comportarse realmente.
Los tipos son cómo los programas se relacionan con las matemáticas, literalmente, por lo que no hay realmente un límite superior sobre lo complicados que pueden llegar a ser, o un punto en el que se puede "terminar" de aprender sobre ellos. Prácticamente todos los recursos fuera de los cursos universitarios de nivel superior están dedicados a cómo funcionan los tipos en un idioma en particular, por lo que también debe decidir eso.
Lo mejor que puedo ofrecer, los tipos se pueden estratificar así:
- Muy débilmente tipado, cosas como JavaScript donde se define [] + {}
- Tecleado débilmente como Python, donde no puedes hacer [] + {}, pero eso no se verifica hasta que lo intentas
- Tecleado débilmente como C o Java, donde no puede hacer [] + {}, pero se verifica en el momento de la compilación, sin embargo, no tiene las características de tipo más avanzadas
- A caballo entre el tipo débil y fuertemente tipado, como la metaprogramación de plantillas de C ++ y el código de Haskell más simple donde los tipos solo imponen propiedades.
- Completamente en Tipografía fuerte, como programas Haskell más complicados donde los tipos hacen cosas, como se muestra arriba
- Muy fuertemente tipado, como Agda o Idris, donde los tipos y valores interactúan y pueden restringirse entre sí. Esto es tan fuerte como los sistemas de tipos, y programar en ellos es lo mismo que escribir pruebas matemáticas sobre lo que hace su programa. Nota: codificar en Agda no es literalmente escribir pruebas matemáticas, los tipos son teorías matemáticas y las funciones con esos tipos son ejemplos constructivos que prueban esas teorías.
En general, cuanto más baja en esta lista, más pueden hacer los tipos por usted, pero al final, está subiendo a la estratosfera y el aire se está volviendo un poco más delgado: el ecosistema del paquete es mucho más pequeño y usted ' Tendrás que escribir más cosas tú mismo en lugar de haber encontrado una biblioteca relevante. La barrera de entrada también aumenta a medida que desciende, ya que debe comprender el sistema de tipos lo suficiente como para escribir programas a gran escala.