Estoy buscando un concepto en teoría de tipos que estoy seguro de que probablemente ha sido explorado, pero no sé el nombre detrás.
Consideremos un lenguaje similar a ML con tipos de producto y suma y un sistema de tipos similar a Hindley-Milner. Usaré la sintaxis OCaml.
Me pregunto cómo dos valores diferentes pueden ser diferentes.
Utilizar
Mi caso de uso es escribir mensajes de error "más claros" en una biblioteca tipo xUnit: si dos valores son diferentes cuando se esperaba que fueran iguales, esto puede ayudar a construir un mensaje mejor y más claro:
Antes de:
Los valores difieren: esperado
{x = [1;2;3;4], y = "a long string"}, conseguido{x = [1;2;3;3], y = "a long string"}
Después:
Los valores difieren: en la posición
.x[3], esperado 4, obtuve 3.
(puede haber una relación con lentes funcionales ya que finalmente estamos construyendo una lente a un valor menor que difiere).
Tipos de productos
Por ejemplo:
type p =
{ x : int
; y : string
}
La igualdad se puede definir como:
let equal a b =
equal_int a.x b.x && equal_string a.y b.y
Pero también es posible reificar las diferencias:
type delta_p =
| Equal
| Diff_x of int * int
| Diff_y of string * string
let diff_p a b =
if not (equal_int a.x b.x) then
Diff_x (a.x, b.x)
else if not (equal_string a.y b.y) then
Diff_y (a.y, b.y)
else
Equal
(puede tener sentido definir un delta_inttipo int * intpara mostrar que es recursivo)
Tipos de suma
Para un tipo de suma hay más formas de diferenciarse: tener un constructor diferente o un valor diferente
type s = X of int | Y of string
type ctor_s =
| Ctor_X
| Ctor_Y
type delta_s =
| Equal
| Diff_ctor of ctor_s * ctor_s
| Diff_X of int * int
| Diff_Y of string * string
let diff_s a b = match (a, b) with
| X xa, X xb ->
if equal_int xa xb then
Equal
else
Diff_X (xa, xb)
| (* Y case similar *)
| X _, Y _ -> Diff_ctor (Ctor_X, Ctor_Y)
| Y _, X _ -> Diff_ctor (Ctor_Y, Ctor_X)
¿Cómo se llama este concepto? ¿Dónde puedo aprender más sobre esto?
¡Gracias!
fuente

Respuestas:
Creo que está buscando una variante tipificada de antiunificación . La antiunificación puede describirse como sigue. Primero, supongamos que tenemos una gramática de términos como sigue:
Aquí,
()y(t, t)denota unidades y pares,C tes un término con un constructor principal, yXes una variable de término, que podría sustituirse por cualquier término.El problema de antiunificación dice, si da dos términos
t1yt2, ¿cuál es el término menos generaltpara que haya sustitucioness1ys2tal ques1(t) = t1ys2(t) = t2?Como ejemplo concreto, dados dos términos
el algoritmo anti-unificación devolvería el anti-unificador
porque las sustituciones
s1 = [X:3, Y:1]ys2 = [X:1, Y:3]aplicadastte daríant1y tet2devolverían. Como comentario aparte, necesitábamos especificar "menos general" porque de lo contrario:con las sustituciones
s1 = [Z:t1]ys2 = [Z:t2]haría el truco.genAumentando este algoritmo para devolver las dos sustituciones
s1ys2lo dejo como ejercicio.fuente