En los lenguajes de programación (especialmente los lenguajes de programación funcional ) y la teoría de tipos , un tipo de opción o tal vez tipo es un tipo polimórfico que representa la encapsulación de un valor opcional; por ejemplo, se utiliza como el tipo de retorno de funciones que pueden o no devolver un valor significativo cuando se aplican. Consiste en un constructor que está vacío (a menudo llamado None
o Nothing
), o que encapsula el tipo de datos original A
(a menudo escrito Just A
o Some A
).
Un concepto distinto, pero relacionado, fuera de la programación funcional, que es popular en la programación orientada a objetos , se llama tipos que aceptan valores NULL (a menudo expresados como A?
). La principal diferencia entre los tipos de opciones y los tipos que aceptan valores NULL es que los tipos de opciones admiten la anidación ( Maybe (Maybe A)
≠ Maybe A
), mientras que los tipos que aceptan valores NULL no ( String??
= String?
).
Aspectos teóricos
En teoría de tipos , se puede escribir como:. Esto expresa el hecho de que para un conjunto dado de valores en, un tipo de opción agrega exactamente un valor adicional (el valor vacío) al conjunto de valores válidos para . Esto se refleja en la programación por el hecho de que en los lenguajes que tienen uniones etiquetadas , los tipos de opciones se pueden expresar como la unión etiquetada del tipo encapsulado más un tipo de unidad . [1]
En la correspondencia Curry-Howard , los tipos de opciones están relacionados con la ley de aniquilación para ∨: x∨1 = 1. [ ¿cómo? ]
Un tipo de opción también puede verse como una colección que contiene uno o cero elementos. [ investigación original? ]
El tipo de opción también es una mónada donde: [2]
return = Just - Envuelve el valor en un tal vezNada >> = f = Nada - Falla si la mónada anterior falla ( Solo x ) >> = f = f x - Tiene éxito cuando ambas mónadas tienen éxito
La naturaleza monádica del tipo de opción es útil para rastrear de manera eficiente fallas y errores. [3]
Nombres y definiciones
En diferentes lenguajes de programación, el tipo de opción tiene varios nombres y definiciones.
- En Agda , se nombra
Maybe
con variantesnothing
yjust a
. - En C ++ 17 se define como la clase de plantilla , se puede usar para crear una opción vacía. ( Podría romper las leyes de las mónadas debido a la gran sobrecarga de los constructores ) .
std::optional<T>
optional()
- En C # , se define como, pero generalmente se escribe como . ( Rompe las leyes de las mónadas ) .
Nullable<T>
T?
- En Coq , se define como .
Inductive option (A:Type) : Type := | Some : A -> option A | None : option A.
- En Elm , se nombra
Maybe
y se define como . [4]type Maybe a = Just a | Nothing
- En Haskell , se nombra
Maybe
y se define como .data Maybe a = Nothing | Just a
- En Idris , se define como .
data Maybe a = Nothing | Just a
- En Java , desde la versión 8, se define como clase final parametrizada . ( Rompe las leyes de las mónadas (el mapa está implementado incorrectamente). )
Optional<T>
- En Julia , se llama . ( Sin embargo, esto ha quedado obsoleto. [5] )
Nullable{T}
- En OCaml , se define como .
type 'a option = None | Some of 'a
- En Perl 6 , este es el valor predeterminado, pero puede agregar un "emoticón" para optar por un tipo sin opción. ( Rompe las leyes de las mónadas (no admite el anidamiento ))
:D
- En Rust , se define como .
enum Option<T> { None, Some(T) }
- En Scala , se define como un tipo extendido por y .
sealed abstract class Option[+A]
final case class Some[+A](value: A)
case object None
- En ML estándar , se define como .
datatype 'a option = NONE | SOME of 'a
- En Swift , se define como, pero generalmente se escribe como . [6]
enum Optional<T> { case none, some(T) }
T?
Ejemplos de
Ada
Ada no implementa tipos de opción directamente, sin embargo, proporciona tipos discriminados que pueden usarse para parametrizar un registro. Para implementar un tipo de Opción, se utiliza un tipo booleano como discriminante; el siguiente ejemplo proporciona un genérico para crear un tipo de opción a partir de cualquier tipo restringido no limitado:
Genérico : cualquier tipo restringido y no limitado. Type Element_Type es privado ; Package Optional_Type es : cuando el discriminante, Has_Element, es verdadero, hay un campo de elemento ; cuando es falso, no hay campos (de ahí la palabra clave nula). Tipo Opcional ( Has_Element : Boolean ) es el caso de registro Has_Element es cuando False => Null ; cuando True => Element : Element_Type ; caso final ; registro final ; end Optional_Type ;
Scala
Scala se implementa Option
como un tipo parametrizado, por lo que una variable puede ser una Option
, a la que se accede de la siguiente manera: [7]
object Main { // Esta función usa la coincidencia de patrones para deconstruir `Option`s def computeV1 ( opt : Option [ Int ]) : String = opt match { case Some ( x ) => s" El valor es: $ x " case None => "Sin valor" } // Esta función usa el método `fold` incorporado def computeV2 ( opt : Option [ Int ]) : String = opt . fold ( "Sin valor" ) ( x => s "El valor es: $ x " ) def main ( args : Array [ String ]) : Unit = { // Definir variables que son `Option`s de tipo` Int` val full = Some ( 42 ) val empty : Option [ Int ] = None // computeV1 (completo) -> El valor es: 42 println ( s "computeV1 (completo) -> $ { computeV1 ( completo ) } " ) // computeV1 (vacío) -> Sin valor println ( s "computeV1 (vacío) -> $ { computeV1 ( vacío ) } " ) // computeV2 (completo) -> El valor es: 42 println ( s "computeV2 (completo) -> $ { computeV2 ( completo ) } " ) // computeV2 (vacío) -> Sin valor println ( s "computeV2 (vacío) -> $ { computeV2 ( vacío ) } " ) } }
Existen dos formas principales de utilizar un Option
valor. El primero, no el mejor, es la coincidencia de patrones , como en el primer ejemplo. La segunda, la mejor práctica es un enfoque monádico, como en el segundo ejemplo. De esta forma, un programa es seguro, ya que no puede generar ninguna excepción o error (por ejemplo, al intentar obtener el valor de una Option
variable que sea igual a None
). Por lo tanto, esencialmente funciona como una alternativa de tipo seguro al valor nulo.
OCaml
OCaml se implementa Option
como un tipo de variante parametrizado. Option
s se construyen y deconstruyen de la siguiente manera:
(* Esta función usa la coincidencia de patrones para deconstruir `option`s *) let compute_v1 = function | Algunos x -> "El valor es:" ^ string_of_int x | Ninguno -> "Sin valor"(* Esta función usa la función incorporada `fold` *) let compute_v2 = Option . fold ~ none : "No value" ~ some :( fun x -> "El valor es:" ^ string_of_int x )let () = (* Definir variables que son `option`s de tipo` int` *) let full = Algunos 42 in let empty = None in (* compute_v1 full -> El valor es: 42 *) print_endline ( "compute_v1 full ->" ^ compute_v1 full ); (* compute_v1 vacío -> Sin valor *) print_endline ( "compute_v1 vacío ->" ^ compute_v1 vacío ); (* compute_v2 full -> El valor es: 42 *) print_endline ( "compute_v2 full ->" ^ compute_v2 full ); (* compute_v2 vacío -> Sin valor *) print_endline ( "compute_v2 vacío ->" ^ compute_v2 vacío )
F#
// Esta función usa la coincidencia de patrones para deconstruir las `opción`s let compute_v1 = function | Algunos x -> sprintf "El valor es:% d" x | Ninguno -> "Sin valor"// Esta función usa la función incorporada `fold` let compute_v2 = Option . fold ( fun _ x -> sprintf "El valor es:% d" x ) "Sin valor"// Definir variables que son `opción` de tipo` int` let full = Algunas 42 let empty = None// compute_v1 full -> El valor es: 42 compute_v1 full |> printfn "compute_v1 full ->% s"// compute_v1 vacío -> Sin valor compute_v1 vacío |> printfn "compute_v1 vacío ->% s"// compute_v2 full -> El valor es: 42 compute_v2 full |> printfn "compute_v2 full ->% s"// compute_v2 vacío -> Sin valor compute_v2 vacío |> printfn "compute_v2 vacío ->% s"
Haskell
- Esta función usa la coincidencia de patrones para deconstruir `Maybe`s computeV1 :: Maybe Int -> String computeV1 ( Just x ) = " El valor es: " ++ show x computeV1 Nothing = " Sin valor "- Esta función usa la función incorporada `foldl` computeV2 :: Maybe Int -> String computeV2 = foldl ( \ _ x -> " El valor es: " ++ show x ) " Sin valor "main :: IO () main = do - Define variables que son `Quizás` de tipo` Int` let full = Just 42 let empty = Nothing - computeV1 completo -> El valor es: 42 putStrLn $ "computeV1 completo ->" ++ computeV1 completo - computeV1 lleno -> Sin valor putStrLn $ "computeV1 vacío ->" ++ computeV1 vacío - computeV2 full -> El valor es: 42 putStrLn $ "computeV2 full ->" ++ computeV2 full - computeV2 lleno -> Sin valor putStrLn $ "computeV2 vacío ->" ++ computeV2 vacío
Rápido
// Esta función utiliza una declaración `` switch` deconstruir Optional`s func computeV1 ( _ opt : Int ?) -> Cadena { interruptor opt { caso . algunos ( deje x ): retorno "El valor es: \ ( x ) " caso . ninguno : devuelve "Sin valor" } }// Esta función usa un enlace opcional para deconstruir la función `Optional`s computeV2 ( _ opt : Int ?) -> String { if let x = opt { return " The value is: \ ( x ) " } else { return " Sin valor " } }// Definir variables que sean `Opcionales` de tipo` Int` let full : Int ? = 42 dejar vacío : Int ? = nada// computeV1 (completo) -> El valor es: 42 print ( "computeV1 (completo) -> \ ( computeV1 ( completo )) " )// computeV1 (vacío) -> Sin valor print ( "computeV1 (vacío) -> \ ( computeV1 ( vacío )) " )// computeV2 (completo) -> El valor es: 42 print ( "computeV2 (completo) -> \ ( computeV2 ( completo )) " )// computeV2 (vacío) -> Sin valor print ( "computeV2 (vacío) -> \ ( computeV2 ( vacío )) " )
Oxido
// Esta función usa una expresión `match` para deconstruir` Option`s fn compute_v1 ( opt : & Option < i32 > ) -> String { opción de coincidencia { Algún ( x ) => formato! ( "El valor es: {}" , x ), Ninguno => "Sin valor" . to_owned (), }}// Esta función usa una expresión `if let` para deconstruir` Option`s fn compute_v2 ( opt : & Option < i32 > ) -> String { si deja Some ( x ) = opt { ¡formato! ( "El valor es: {}" , x ) } más { "Sin valor" . to_owned () }}// Esta función usa el método incorporado `map_or` fn compute_v3 ( opt : & Option < i32 > ) -> String { optar . map_or ( "Sin valor" . to_owned (), | x | format! ( "El valor es: {}" , x )) }fn main () { // Definir variables que sean `Option`s de tipo` i32` let full = Some ( 42 ); dejar vacío : Opción < i32 > = Ninguno ; // compute_v1 (& full) -> El valor es: 42 println! ( "compute_v1 (& full) -> {}" , compute_v1 ( & full )); // compute_v1 (& vacio) -> Sin valor println! ( "compute_v1 (& vacío) -> {}" , compute_v1 ( & vacío )); // compute_v2 (& full) -> El valor es: 42 println! ( "compute_v2 (& full) -> {}" , compute_v2 ( & full )); // compute_v2 (& vacio) -> Sin valor println! ( "compute_v2 (& vacío) -> {}" , compute_v2 ( & vacío )); // compute_v3 (& full) -> El valor es: 42 println! ( "compute_v3 (& full) -> {}" , compute_v3 ( & full )); // compute_v3 (& vacio) -> Sin valor println! ( "compute_v3 (y vacío) -> {}" , compute_v3 ( y vacío )) }
Nim
opciones de importación# Este proc utiliza los procsos GET` incorporados en `isSome` y` `deconstruir Option`s proc de cómputo ( opt : Opción [ int ] ): cadena = si opt . isSome : "El valor es:" & $ opt . obtener más : "Sin valor"# Definir variables que sean `Opcionales` de tipo` Int` let full = some ( 42 ) empty = none ( int )# compute (full) -> El valor es: 42 echo "compute (full) ->" , compute ( full )# compute (vacío) -> Sin valor echo "compute (vacío) ->" , compute ( vacío )
Ver también
Referencias
- ↑ Milewski, Bartosz (13 de enero de 2015). "Tipos de datos algebraicos simples" . Café de programación de Bartosz Milewski . Tipos de suma. "Podríamos haber codificado Quizás como: datos Quizás a = Either () a". Archivado desde el original el 18 de agosto de 2019 . Consultado el 18 de agosto de 2019 .
- ^ "Un puñado de mónadas: ¡aprende un Haskell para siempre!" . www.learnyouahaskell.com . Consultado el 18 de agosto de 2019 .
- ^ Hutton, Graham (25 de noviembre de 2017). "¿Qué es una mónada?" . Computerphile Youtube . Consultado el 18 de agosto de 2019 .
- ^ "Quizás · Una introducción a Elm" . guide.elm-lang.org .
- ^ "Notas de la versión de Julia v0.7.0 · El lenguaje de Julia" . docs.julialang.org .
- ^ "Documentación para desarrolladores de Apple" . developer.apple.com . Consultado el 6 de septiembre de 2020 .
- ^ Martin Odersky; Lex Spoon; Bill Venners (2008). Programación en Scala . Artima Inc. págs. 282–284. ISBN 978-0-9815316-0-1. Consultado el 6 de septiembre de 2011 .