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⊥ → Aabsurd
absurd
⊥→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()))
?absurd
absurd
throw
Para 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 a
que representa una estructura de árbol general conf
nodos en forma de hojas y hojas que contienena
s:data Free f a = Op (f (Free f a)) | Var a
Estos árboles se pueden plegar con la siguiente función:
Brevemente, esta operación se coloca
alg
en los nodos ygen
en 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 f
y se puede definir comotype Fix f = Free f ⊥
(es decir, árboles conf
nodos 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 elgen
para este pliegue eabsurd
ilustra 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
NULL
en 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 aNULL
dondechar*
se esperaba; Del mismo modo, el tipo deundefined
JavaScript 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 retornaInt
en 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.Int
exit()
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
NULL
es 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
maybe
mónada, deletreadaOptional<T>
oT?
. Hay muchas formas de interactuar con él.Puede usar desenvoltura condicional como
Puedes usar
map
,flatMap
para 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
fatalError
tiene tipo() -> Never
(()
esVoid
, tipo de unidadNever
Swift , es el tipo inferior de Swift). Llamarlo produceNever
, que no es compatible con loT
esperado 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 queNever
sea un subtipo de todo tipo.Si
Never
fue 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) -> T
firma 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