Una de las propiedades que definen el o escribe el vacío es que existe una función para cada tipo . De hecho, existe una función única de este tipo. Por lo tanto, es bastante razonable que esta función se proporcione como parte de la biblioteca estándar. A menudo se llama algo así . (En los sistemas con subtipo, esto podría manejarse simplemente haciendo que sea un subtipo de cada tipo. Entonces la conversión implícita es . Otro enfoque relacionado es definir como que simplemente puede ser instanciado para cualquier tipo.)⊥⊥ → AUN⊥ ⊥ ∀ α . αabsurd⊥absurd ⊥∀ α . α
Definitivamente quiere tener una función o un equivalente porque es lo que le permite hacer uso de funciones que producen . Por ejemplo, digamos que me dan una suma Tipo . Hago un análisis de caso y en el caso voy a lanzar una excepción usando . En el caso, voy a usar . En general, yo quiero un valor de tipo así que tengo que hacer algo para convertir una en un . Eso es lo que me dejaría hacer.⊥E+AEthrow:E→⊥Af:A→BB⊥Babsurd
Dicho esto, no hay un montón de razones para definir sus propias funciones de . Por definición, serían necesariamente instancias de . Aún así, puede hacerlo si no lo proporciona la biblioteca estándar, o si desea una versión especializada en tipos para ayudar a la verificación / inferencia de tipos. Puede, sin embargo, producir fácilmente las funciones que terminarán una instancia de un tipo como .⊥→A⊥ → Aabsurdabsurd⊥→A
Aunque no hay muchas razones para escribir una función de este tipo, en general aún debería permitirse . Una razón es que simplifica las herramientas / macros de generación de código.
Derek Elkins dejó SE
fuente
(x ? 3 : throw new Exception())se reemplaza para fines de análisis con algo más parecido(x ? 3 : absurd(throw new Exception()))?absurdabsurdthrowPara agregar a lo que se ha dicho acerca de la función
absurd: ⊥ -> a, tengo un ejemplo concreto de dónde esta función es realmente útil.Considere el tipo de datos Haskell
Free f aque representa una estructura de árbol general confnodos en forma de hojas y hojas que contienenas:data Free f a = Op (f (Free f a)) | Var aEstos árboles se pueden plegar con la siguiente función:
Brevemente, esta operación se coloca
algen los nodos ygenen las hojas.Ahora al grano: todas las estructuras de datos recursivas se pueden representar utilizando un tipo de datos de punto fijo. En Haskell esto es
Fix fy se puede definir comotype Fix f = Free f ⊥(es decir, árboles confnodos en forma y sin hojas fuera del functorf). Tradicionalmente, esta estructura también tiene un pliegue, llamadocata:Lo que da un uso bastante ordenado de lo absurdo: dado que el árbol no puede tener hojas (ya que ⊥ no tiene habitantes más que
undefined), ¡nunca es posible usar elgenpara este pliegue eabsurdilustra eso!fuente
El tipo inferior es un subtipo de cualquier otro tipo, que puede ser extremadamente útil en la práctica. Por ejemplo, el tipo de
NULLen una versión teórica segura de tipo de C debe ser un subtipo de cualquier otro tipo de puntero; de lo contrario, no podría, por ejemplo, regresar aNULLdondechar*se esperaba; Del mismo modo, el tipo deundefinedJavaScript teórico seguro de tipo debe ser un subtipo de cualquier otro tipo en el lenguaje.Como un tipo de retorno de función, también es muy útil tener ciertas funciones que nunca regresan. En un lenguaje fuertemente tipado con excepciones, por ejemplo, ¿qué tipo debería⊥
exit()o deberíathrow()regresar? Nunca devuelven el flujo de control a su interlocutor. Y dado que el tipo inferior es un subtipo de cualquier otro tipo, es perfectamente válido para una función que retornaInten lugar de return es decir, una función que regresa también puede elegir no regresar en absoluto. (Tal vez llama , o tal vez entra en un bucle infinito.) Es bueno tenerlo, porque si alguna vez la función regresa o no es famosa por decidir.Intexit()Finalmente, es muy útil para escribir restricciones. Suponga que desea restringir todos los parámetros en "ambos lados", proporcionando un tipo que debe ser un supertipo del parámetro y otro tipo que debe ser un subtipo. Desde abajo es un subtipo de todo tipo, se puede expresar "cualquier subtipo de S" como . O bien, puede expresar "cualquier tipo" como .⊥≺T≺S ⊥≺T≺⊤
fuente
NULLes un tipo de unidad, ¿no es distinto de ⊥ que es el tipo vacío?void*, necesitarías un tipo específico para él que podría usarse para cualquier tipo de puntero.<:por ejemplo, SistemaSe me ocurre un uso, y es algo que se ha considerado como una mejora del lenguaje de programación Swift.
Swift tiene una
maybemónada, deletreadaOptional<T>oT?. Hay muchas formas de interactuar con él.Puede usar desenvoltura condicional como
Puedes usar
map,flatMappara transformar los valores!de tipo(T?) -> T) para desenvolver forzosamente el contenido, de lo contrario desencadena un bloqueoEl operador de fusión nula (
??de tipo(T?, T) -> T) para tomar su valor o usar un valor predeterminado:Desafortunadamente, no había una forma concisa de decir "desenvolver o lanzar un error" o "desenvolver o bloquearse con un mensaje de error personalizado". Algo como
no se compila, porque
fatalErrortiene tipo() -> Never(()esVoid, tipo de unidadNeverSwift , es el tipo inferior de Swift). Llamarlo produceNever, que no es compatible con loTesperado como un operando correcto de??.En un intento de remediar esto, Swift Evolution propsoal
SE-0217: se presentó el operador " Desenvolver o morir" . Finalmente fue rechazado , pero despertó interés en hacer queNeversea un subtipo de todo tipo.Si
Neverfue hecho para ser un subtipo de todos los tipos, entonces el ejemplo anterior será compilable:porque el sitio de llamada de
??tiene tipo(T?, Never) -> T, que sería compatible con la(T?, T) -> Tfirma de??.fuente
Swift tiene un tipo "Nunca" que parece ser bastante parecido al tipo inferior: Una función declarada para devolver Nunca nunca puede regresar, una función con un parámetro de tipo Nunca nunca se puede llamar.
Esto es útil en relación con los protocolos, donde puede haber una restricción debido al sistema de tipos del lenguaje de que una clase debe tener una determinada función, pero sin el requisito de que esta función deba llamarse alguna vez, y sin ningún requisito sobre qué tipos de argumentos sería.
Para obtener más información, debe echar un vistazo a las publicaciones más recientes en la lista de correo de evolución rápida.
fuente