Cómo lo pienso:
type se utiliza para definir nuevos tipos de unión:
type Thing = Something | SomethingElse
Antes de esta definición Somethingy SomethingElseno significaba nada. Ahora ambos son del tipo Thing, que acabamos de definir.
type alias se usa para dar un nombre a algún otro tipo que ya existe:
type alias Location = { lat:Int, long:Int }
{ lat = 5, long = 10 }tiene tipo { lat:Int, long:Int }, que ya era un tipo válido. Pero ahora también podemos decir que tiene tipoLocation porque es un alias para el mismo tipo.
Vale la pena señalar que lo siguiente se compilará y mostrará sin problemas "thing". Aunque especificamos thingis a Stringy aliasedStringIdentitytoma an AliasedString, no obtendremos un error de que existe una falta de coincidencia de tipos entre String/ AliasedString:
import Graphics.Element exposing (show)
type alias AliasedString = String
aliasedStringIdentity: AliasedString -> AliasedString
aliasedStringIdentity s = s
thing : String
thing = "thing"
main =
show <| aliasedStringIdentity thing
{}sintaxis de registro, ¿está definiendo un nuevo tipo?{ lat:Int, long:Int }no define un nuevo tipo. Ese ya es un tipo válido.type alias Location = { lat:Int, long:Int }tampoco define un nuevo tipo, solo le da otro nombre (quizás más descriptivo) a un tipo ya válido.type Location = Geo { lat:Int, long:Int }definiría un nuevo tipo (Location)La clave es la palabra
alias. En el curso de la programación, cuando quieres agrupar cosas que pertenecen juntas, lo pones en un registro, como en el caso de un puntoo un expediente de estudiante.
Ahora, si necesita pasar estos registros, tendrá que deletrear todo el tipo, como:
Si pudieras poner un alias en un punto, ¡la firma sería mucho más fácil de escribir!
Entonces, un alias es una forma abreviada de otra cosa. Aquí, es una abreviatura de un tipo de registro. Puede pensar en ello como dar un nombre a un tipo de registro que utilizará con frecuencia. Por eso se llama alias: es otro nombre para el tipo de registro desnudo que está representado por
{ x:Int, y:Int }Considerando que
typeresuelve un problema diferente. Si viene de OOP, es el problema que resuelve con la herencia, la sobrecarga de operadores, etc., a veces, desea tratar los datos como algo genérico y, a veces, desea tratarlos como algo específico.Un lugar común donde esto sucede es cuando se transmiten mensajes, como el sistema postal. Cuando envía una carta, desea que el sistema postal trate todos los mensajes como lo mismo, por lo que solo tiene que diseñar el sistema postal una vez. Y además, el trabajo de enrutar el mensaje debe ser independiente del mensaje que contiene. Solo cuando la carta llega a su destino te importa cuál es el mensaje.
De la misma manera, podríamos definir a
typecomo una unión de todos los diferentes tipos de mensajes que podrían ocurrir. Digamos que estamos implementando un sistema de mensajería entre estudiantes universitarios y sus padres. Así que solo hay dos mensajes que los universitarios pueden enviar: "Necesito dinero para cerveza" y "Necesito calzoncillos".Así que ahora, cuando diseñamos el sistema de enrutamiento, los tipos de nuestras funciones pueden simplemente pasar
MessageHome, en lugar de preocuparse por todos los diferentes tipos de mensajes que podrían ser. Al sistema de enrutamiento no le importa. Solo necesita saber que es unMessageHome. Solo cuando el mensaje llega a su destino, la casa de los padres, es necesario averiguar qué es.Si conoce la arquitectura Elm, la función de actualización es una declaración de caso gigante, porque ese es el destino al que se enruta el mensaje y, por lo tanto, se procesa. Y usamos tipos de unión para tener un solo tipo con el que lidiar cuando se pasa el mensaje, pero luego podemos usar una declaración de caso para averiguar exactamente qué mensaje era, para que podamos lidiar con él.
fuente
Permítanme complementar las respuestas anteriores centrándome en casos de uso y proporcionando un pequeño contexto sobre las funciones y los módulos del constructor.
Usos de
type aliasCrear un alias y una función constructora para un registro
Este es el caso de uso más común: puede definir un nombre alternativo y una función constructora para un tipo particular de formato de registro.
Definir el alias de tipo implica automáticamente la siguiente función constructora (pseudocódigo):
Person : String -> Int -> { name : String, age : Int }Esto puede resultar útil, por ejemplo, cuando se desea escribir un decodificador Json.
Especifique los campos obligatorios
A veces lo llaman "registros extensibles", lo que puede resultar engañoso. Esta sintaxis se puede utilizar para especificar que está esperando algún registro con campos particulares presentes. Como:
Entonces puede usar la función anterior de esta manera (por ejemplo, en su vista):
La charla de Richard Feldman sobre ElmEurope 2017 puede proporcionar más información sobre cuándo vale la pena usar este estilo.
Cambiar el nombre de las cosas
Puede hacer esto, porque los nuevos nombres podrían proporcionar un significado adicional más adelante en su código, como en este ejemplo
Quizás un mejor ejemplo de este tipo de uso en core es
Time.Volver a exponer un tipo de un módulo diferente
Si está escribiendo un paquete (no una aplicación), es posible que necesite implementar un tipo en un módulo, tal vez en un módulo interno (no expuesto), pero desea exponer el tipo de un módulo (público) diferente. O, alternativamente, desea exponer su tipo de varios módulos.
Tasken core y Http.Request en Http son ejemplos del primero, mientras que Json.Encode.Value y Json.Decode.Value par es un ejemplo del último.Solo puede hacer esto cuando, de lo contrario, desea mantener el tipo opaco: no expone las funciones del constructor. Para obtener más información, consulte los usos a
typecontinuación.Vale la pena notar que en los ejemplos anteriores solo el # 1 proporciona una función de constructor. Si expone su alias de tipo en # 1 así
module Data exposing (Person), expondrá el nombre del tipo así como la función constructora.Usos de
typeDefinir un tipo de unión etiquetada
Este es el caso de uso más común, un buen ejemplo de ello es el
Maybetipo en el núcleo :Cuando define un tipo, también define sus funciones de constructor. En el caso de Maybe, estos son (pseudocódigo):
Lo que significa que si declaras este valor:
Puede crearlo por
o
Las etiquetas
JustyNothingno solo sirven como funciones de constructor, también sirven como destructores o patrones en unacaseexpresión. Lo que significa que usando estos patrones puedes ver dentro de unMaybe:Puede hacer esto, porque el módulo Quizás se define como
También podría decir
Los dos son equivalentes en este caso, pero ser explícito se considera una virtud en Elm, especialmente cuando está escribiendo un paquete.
Ocultar detalles de implementación
Como se señaló anteriormente, es una elección deliberada que las funciones del constructor
Maybesean visibles para otros módulos.Sin embargo, hay otros casos en los que el autor decide ocultarlos. Un ejemplo de esto en el núcleo es
Dict. Como consumidor del paquete, no debería poder ver los detalles de implementación del algoritmo del árbol Rojo / Negro detrásDicty meterse con los nodos directamente. Ocultar las funciones del constructor obliga al consumidor de su módulo / paquete a crear solo valores de su tipo (y luego transformar esos valores) a través de las funciones que expone.Esta es la razón por la que a veces aparecen cosas como esta en el código
A diferencia de la
type aliasdefinición en la parte superior de esta publicación, esta sintaxis crea un nuevo tipo de "unión" con solo una función de constructor, pero esa función de constructor se puede ocultar de otros módulos / paquetes.Si el tipo se expone así:
Solo el código del
Datamódulo puede crear un valor de Persona y solo ese código puede coincidir con el patrón.fuente
La principal diferencia, como yo lo veo, es si el verificador de tipos le gritará si usa el tipo "sinómico".
Cree el siguiente archivo, colóquelo en algún lugar y ejecútelo
elm-reactor, luego vaya ahttp://localhost:8000para ver la diferencia:Si descomenta
2.y comenta1., verá:fuente
An
aliases solo un nombre más corto para algún otro tipo, similarclassen OOP. Exp:Un
type(sin alias) le permitirá definir su propio tipo, por lo que se puede definir como tiposInt,String... para que usted aplicación. Por ejemplo, en el caso común, se puede usar para la descripción de un estado de aplicación:Para que puedas manejarlo fácilmente en
viewolmo:Creo que conoces la diferencia entre
typeytype alias.Pero por qué y cómo usar
typeytype aliases importante con laelmaplicación, ustedes pueden consultar el artículo de Josh Clayton.fuente