Escriba "formas en que los valores pueden ser diferentes"

8

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!

Etienne Millon
fuente
2
Una cremallera es un "puntero" a una ubicación. No sé si alguien estudió formas de mostrarle una cremallera al usuario.
Andrej Bauer el
Realmente no se discutió en general, pero el caso de uso me recuerda a The View from the Left , sección 7, donde hacen un verificador de tipo verificado que informa la diferencia precisa entre el tipo esperado y general. La Figura 15 tiene el tipo Isnt que es análogo a su caso de uso.
Max New
Gracias por los consejos. Me parece que las cremalleras tienen más que ver con "moverse" de izquierda a derecha que de enfocar, pero eso también es un efecto que tienen. Eso parece bastante relacionado con los patrones de vista de hecho.
Étienne Millon

Respuestas:

9

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:

t ::= () | (t, t) | C t | X 

Aquí, ()y (t, t)denota unidades y pares, C tes un término con un constructor principal, y Xes una variable de término, que podría sustituirse por cualquier término.

El problema de antiunificación dice, si da dos términos t1y t2, ¿cuál es el término menos general tpara que haya sustituciones s1y s2tal que s1(t) = t1y s2(t) = t2?

Como ejemplo concreto, dados dos términos

t1 = Cons(3, Cons(2, Cons(1, Nil)))
t2 = Cons(1, Cons(2, Cons(3, Nil)))

el algoritmo anti-unificación devolvería el anti-unificador

t = Cons(X, Cons(2, Cons(Y, Nil)))

porque las sustituciones s1 = [X:3, Y:1]y s2 = [X:1, Y:3]aplicadas tte darían t1y te t2devolverían. Como comentario aparte, necesitábamos especificar "menos general" porque de lo contrario:

t' = Z 

con las sustituciones s1 = [Z:t1]y s2 = [Z:t2]haría el truco.

gen :Tmirmetro×TmirmetroVunar

antiunify ()       ()         = ()
antiunify (t1, t2) (t1', t2') = (antiunify t1 t1', antiunify t2 t2')
antiunify (C t)    (C t')     = C (antiunify t t')
antiunify t        t'         = gen(t, t') -- default: t and t' dissimilar 

Aumentando este algoritmo para devolver las dos sustituciones s1y s2lo dejo como ejercicio.

Neel Krishnaswami
fuente
Gracias por el término (juego de palabras). Parece que podría ser eso. Un álgebra mecanografiada de "caminos" como este sería genial. ¡Gracias!
Étienne Millon