Tipos de suma: ¿por qué en Haskell es `show (Int | Double)` diferente a `(show Int) | (mostrar Doble) `

9

¿Por qué no son equivalentes?

show $ if someCondition then someInt else some double

y

if someCondition then show someInt else show someDouble

Entiendo que si aísla la if ... elseparte en el primer ejemplo de una expresión en sí misma, entonces no puede representar su tipo con un tipo de suma anónima, el tipo de Int | Doublealgo que podría hacer fácilmente en TypeScript (mencionando TypeScript porque es el tipo usé el idioma a menudo y eso admite los tipos de Suma), y tendría que recurrir al uso de los Eitherdatos que luego llamaría show.

El ejemplo que di aquí es trivial, pero para mí tiene más sentido pensar "Ok, vamos a mostrar algo, y ese algo depende de someCondition" en lugar de "Ok, si alguna condición es verdadera, entonces muestra algo, de lo contrario, muestra algo doble", y también permite para una menor duplicación de código (aquí el programa se repite dos veces, pero también podría ser una aplicación de función larga y, en lugar de una if ... else, podría haber> 2 ramas para considerar)

En mi opinión, debería ser fácil para el compilador verificar si cada uno de los tipos que forman el tipo de suma (aquí Int | Double) podría usarse como parámetro para showfuncionar y decide si los tipos son correctos o no. Aún mejor es que la showfunción siempre devuelve un stringsin importar los tipos de parámetros, por lo que el compilador no tiene que llevar consigo todas las "ramas" posibles (por lo que todos los tipos posibles).

¿Es por elección que tal característica no existe? ¿O lo está implementando más difícil de lo que creo?

Mehdi Saffar
fuente
2
An if ... then ... else ..., debe tener el mismo tipo en la parte theny else. Puede verlo como un operador ternario en algunos lenguajes de programación.
Willem Van Onsem
1
Estoy de acuerdo con el making all conversions explicit. En mi pregunta, no quiero que Haskell emita Inta un Doubleviceversa. Acabo de usar esos dos tipos como ejemplo. Podrías reemplazar cada Intcon ay Doublecon ben mi pregunta de dónde derivan ambos tipos Show. Entiendo que no hay anonymous sum typesen Haskell, pero me gustaría saber por qué ese es el caso y qué nos impide diseñar el lenguaje para tenerlo.
Mehdi Saffar
44
Creo que estos tipos se llaman tipos de unión . Un tipo de suma es esencialmente una variante etiquetada del tipo de unión, donde cada valor debe llevar una etiqueta izquierda / derecha más allá del valor del tipo interno. Espero que la inferencia de tipos con tipos de unión, con todas las características de nivel de tipo de Haskell, sea muy difícil de lograr. Si x :: Int | Booly tenemos que compilar show x, no hay una manera fácil de saber qué puntero a función usar para llamar show, en un RTS basado en borrado de tipo. Probablemente necesitemos mantener información de nivel de tipo en tiempo de ejecución.
chi
1
No tener tipos de suma anónimos es una decisión de diseño de los diseñadores de Haskell. No estoy muy seguro de qué tipo de beneficio aportarían a la mesa, aunque sí veo dónde complicarían las cosas. Entonces, supongo que se quedan fuera porque la relación costo / beneficio no está allí. Pero para estar absolutamente seguro, debe preguntar a los diseñadores de idiomas originales y / o mantenedores actuales. No creo que sea una gran pregunta SO, porque hay muchas opiniones y gustos personales involucrados en el diseño de un lenguaje.
n. 'pronombres' m.
44
(String, Int)No es anónimo. Es solo un tipo de producto normal con una sintaxis divertida. (String | Int)Sería muy diferente. Comience preguntándose si (Int|Int)debería ser idéntico Inty por qué.
n. 'pronombres' m.

Respuestas:

8

Todas las partes de una expresión deben estar bien escritas. El tipo de if someCondition then someInt else someDoubletendría que ser algo así exists a. Show a => a, pero Haskell no admite ese tipo de cuantificación existencial.

Actualización: como Chi señala en un comentario , esto también sería posible si Haskell tuviera soporte para los tipos de unión / intersección (que no son lo mismo que los tipos de suma / producto), pero desafortunadamente no.

Joseph Sible-Reinstate a Monica
fuente
¿Podría explicar la diferencia entre los tipos de unión / intersección y los tipos de suma / producto? Siempre he pensado que eran lo mismo, excepto por el anonimato.
Mehdi Saffar
1
@MehdiSaffar Anónimo como sin etiquetar, no como en un constructor sin nombre. En otras palabras, si tiene un Int ∪ Double, entonces sabría que tiene uno de los dos, pero no podría establecer una coincidencia de patrones para ver cuál, por lo que solo podría hacer cosas que serían válidas para ambas posibilidades.
Joseph Sible-Reinstate a Monica el
2
Para mayor claridad, TypeScript tiene información de tipo disponible en tiempo de ejecución, por lo que tiene un typeofoperador que puede compensar la falta de etiquetado y ver qué tipo se utiliza de todos modos. Haskell está completamente borrado, por lo que si admitiera esta función, entonces no habría ningún equivalente a eso.
Joseph Sible-Reinstate a Monica el
7

Hay tipos de productos con sintaxis ligera, escrita (,), en Haskell. Una cosa sería que un tipo de suma con una sintaxis ligera, algo así (Int | String), sería una gran idea. La realidad es mas complicada. Veamos por qué (me estoy tomando algunas libertades Num, no son importantes).

if someCondition then 42 else "helloWorld"

Si esto debería devolver un valor de tipo como (Int | String), ¿qué debería devolver el siguiente?

if someCondition then 42 else 0

(Int | Int)obviamente, pero si esto es distinto de lo normal, Intentonces estamos en serios problemas. Por (Int | Int)lo tanto, debe ser idéntico a simple Int.

Uno puede ver de inmediato que esto no es solo una sintaxis ligera para los tipos de suma, sino una característica de lenguaje completamente nueva. Un tipo diferente de sistema de tipos si se quiere. ¿Deberíamos tener uno?

Veamos esta función.

mysteryType x a b = if x then a else b

Ahora que tipo mysteryTypetiene? Obviamente

mysteryType :: Bool -> a -> b -> (a|b)

¿Correcto? ¿Qué pasa si ay bson del mismo tipo?

let x = mysteryType True 42 0

Esto debería ser claro Intcomo hemos acordado anteriormente. Ahora a mysteryTypeveces devuelve un tipo de suma anónima, y ​​otras veces no, dependiendo de los argumentos que pase. ¿Cómo combinarías un patrón con esa expresión? ¿Qué demonios puedes hacer con él? Excepto cosas triviales como "show" (o cualquier método de otras clases de tipos de las que sería una instancia), no mucho. A menos que agregue información de tipo de tiempo de ejecución al idioma, es decir, typeofestá disponible, y eso hace que Haskell sea un idioma completamente diferente.

Así que sí. ¿Por qué no es Haskell un TypeScript? Porque no necesitamos otro TypeScript. Si desea TypeScript, ya sabe dónde encontrarlo.

norte. 'pronombres' m.
fuente
1
@MichaWiedenmann Francamente, no sé si "relevante" es la palabra correcta. Creo que es útil de una forma u otra. Sí, me detuve por un momento y pensé si incluirlo. Pero se sabe que me equivoco a veces.
n. 'pronombres' m.
No hay problema, es tu publicación, tú decides.
Micha Wiedenmann
¿Cuáles son tus pronombres?
dfeuer